You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/11/28 18:02:23 UTC

[commons-vfs] 01/02: Sort members.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit ee8684c7ecd227ccf5901a163cd635c2a5ce01ee
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Nov 28 12:04:04 2021 -0500

    Sort members.
---
 .../vfs2/provider/webdav/WebdavFileObject.java     |  18 +-
 .../vfs2/provider/webdav/WebdavFileProvider.java   |   8 +-
 .../vfs2/provider/webdav/WebdavFileSystem.java     |  12 +-
 .../webdav/WebdavFileSystemConfigBuilder.java      |  38 +-
 .../vfs2/provider/webdav/test/JackrabbitMain.java  |  34 +-
 .../vfs2/provider/webdav/test/JcrUtils.java        |  12 +-
 .../webdav/test/WebdavProviderTestCase.java        |  16 +-
 .../webdav/test/WebdavVersioningTests.java         |  26 +-
 .../vfs2/provider/webdav4/Webdav4FileObject.java   |  18 +-
 .../vfs2/provider/webdav4/Webdav4FileProvider.java |   8 +-
 .../webdav4/Webdav4FileSystemConfigBuilder.java    |  38 +-
 .../provider/webdav4s/Webdav4sFileProvider.java    |   8 +-
 .../vfs2/provider/webdav4/test/JcrUtils.java       |  12 +-
 .../webdav4/test/Webdav4ProviderTestCase.java      |  16 +-
 .../webdav4/test/Webdav4VersioningTests.java       |  26 +-
 .../org/apache/commons/vfs2/CacheStrategy.java     |   6 +-
 .../org/apache/commons/vfs2/FileDepthSelector.java |  18 +-
 .../apache/commons/vfs2/FileFilterSelector.java    |  22 +-
 .../java/org/apache/commons/vfs2/FileListener.java |  18 +-
 .../java/org/apache/commons/vfs2/FileObject.java   |  20 +-
 .../org/apache/commons/vfs2/FileSelectInfo.java    |  12 +-
 .../java/org/apache/commons/vfs2/FileSystem.java   | 158 ++--
 .../apache/commons/vfs2/FileSystemException.java   |  50 +-
 .../org/apache/commons/vfs2/FileSystemOptions.java |  86 +-
 .../java/org/apache/commons/vfs2/FileType.java     |  22 +-
 .../commons/vfs2/InvertIncludeFileSelector.java    |   4 +-
 .../java/org/apache/commons/vfs2/NameScope.java    |   6 +-
 .../commons/vfs2/UserAuthenticationData.java       |  46 +-
 .../main/java/org/apache/commons/vfs2/VfsLog.java  | 104 +--
 .../commons/vfs2/auth/StaticUserAuthenticator.java |  72 +-
 .../commons/vfs2/cache/DefaultFilesCache.java      |  36 +-
 .../commons/vfs2/cache/FileSystemAndNameKey.java   |   8 +-
 .../apache/commons/vfs2/cache/LRUFilesCache.java   |  94 +--
 .../apache/commons/vfs2/cache/NullFilesCache.java  |  14 +-
 .../vfs2/cache/OnCallRefreshFileObject.java        |  34 +-
 .../apache/commons/vfs2/filter/NameFileFilter.java |  44 +-
 .../commons/vfs2/filter/PrefixFileFilter.java      |  42 +-
 .../commons/vfs2/filter/SuffixFileFilter.java      |  36 +-
 .../commons/vfs2/filter/WildcardFileFilter.java    | 106 +--
 .../commons/vfs2/impl/DecoratedFileObject.java     |  10 +-
 .../commons/vfs2/impl/DefaultFileContentInfo.java  |   8 +-
 .../vfs2/impl/DefaultFileSystemConfigBuilder.java  |  30 +-
 .../vfs2/impl/DefaultVfsComponentContext.java      |  52 +-
 .../vfs2/impl/PrivilegedFileReplicator.java        | 140 ++--
 .../commons/vfs2/impl/ProviderConfiguration.java   |  48 +-
 .../org/apache/commons/vfs2/impl/Resource.java     |  38 +-
 .../vfs2/impl/StandardFileSystemManager.java       | 408 ++++-----
 .../commons/vfs2/impl/SynchronizedFileObject.java  |  44 +-
 .../apache/commons/vfs2/impl/VFSClassLoader.java   | 166 ++--
 .../apache/commons/vfs2/impl/VirtualFileName.java  |   8 +-
 .../commons/vfs2/impl/VirtualFileProvider.java     |  30 +-
 .../commons/vfs2/impl/VirtualFileSystem.java       |  66 +-
 .../operations/AbstractFileOperationProvider.java  |  32 +-
 .../vfs2/operations/DefaultFileOperations.java     |  48 +-
 .../commons/vfs2/operations/FileOperations.java    |  12 +-
 .../commons/vfs2/operations/vcs/VcsCheckout.java   |  16 +-
 .../commons/vfs2/operations/vcs/VcsCommit.java     |  16 +-
 .../apache/commons/vfs2/operations/vcs/VcsLog.java |  12 +-
 .../commons/vfs2/operations/vcs/VcsLogEntry.java   |  18 +-
 .../commons/vfs2/operations/vcs/VcsRevert.java     |  12 +-
 .../commons/vfs2/operations/vcs/VcsUpdate.java     |  16 +-
 .../commons/vfs2/provider/AbstractFileName.java    | 390 ++++-----
 .../vfs2/provider/AbstractFileProvider.java        | 100 +--
 .../commons/vfs2/provider/AbstractFileSystem.java  | 530 ++++++------
 .../vfs2/provider/AbstractLayeredFileProvider.java |  56 +-
 .../provider/AbstractOriginatingFileProvider.java  |  56 +-
 .../AbstractRandomAccessStreamContent.java         |  48 +-
 .../vfs2/provider/AbstractVfsComponent.java        |  50 +-
 .../vfs2/provider/AbstractVfsContainer.java        |  24 +-
 .../vfs2/provider/CompositeFileProvider.java       |  14 +-
 .../commons/vfs2/provider/DefaultFileContent.java  | 924 ++++++++++-----------
 .../vfs2/provider/DefaultFileSelectorInfo.java     |  18 +-
 .../vfs2/provider/DefaultURLConnection.java        |  36 +-
 .../commons/vfs2/provider/DelegateFileObject.java  | 322 +++----
 .../vfs2/provider/FileContentThreadData.java       |  16 +-
 .../apache/commons/vfs2/provider/FileProvider.java |  28 +-
 .../commons/vfs2/provider/GenericFileName.java     | 116 +--
 .../commons/vfs2/provider/GenericURLFileName.java  |  62 +-
 .../commons/vfs2/provider/LayeredFileName.java     |  26 +-
 .../vfs2/provider/LayeredFileNameParser.java       |  60 +-
 .../commons/vfs2/provider/LocalFileProvider.java   |  24 +-
 .../apache/commons/vfs2/provider/URLFileName.java  |  62 +-
 .../apache/commons/vfs2/provider/VfsComponent.java |  24 +-
 .../commons/vfs2/provider/VfsComponentContext.java |  52 +-
 .../vfs2/provider/bzip2/Bzip2FileObject.java       |  30 +-
 .../vfs2/provider/bzip2/Bzip2FileSystem.java       |   8 +-
 .../compressed/CompressedFileFileObject.java       |  52 +-
 .../compressed/CompressedFileFileProvider.java     |   4 +-
 .../vfs2/provider/ftps/FtpsClientFactory.java      |  46 +-
 .../provider/ftps/FtpsFileSystemConfigBuilder.java | 138 +--
 .../commons/vfs2/provider/gzip/GzipFileObject.java |  14 +-
 .../commons/vfs2/provider/gzip/GzipFileSystem.java |   8 +-
 .../commons/vfs2/provider/jar/JarFileObject.java   |  70 +-
 .../commons/vfs2/provider/jar/JarFileSystem.java   |  60 +-
 .../vfs2/provider/jar/JarURLConnectionImpl.java    |  52 +-
 .../commons/vfs2/provider/ram/RamFileData.java     | 198 ++---
 .../commons/vfs2/provider/ram/RamFileObject.java   | 128 +--
 .../vfs2/provider/ram/RamFileOutputStream.java     |  44 +-
 .../provider/ram/RamFileRandomAccessContent.java   | 346 ++++----
 .../commons/vfs2/provider/ram/RamFileSystem.java   | 156 ++--
 .../vfs2/provider/res/ResourceFileName.java        |  30 +-
 .../vfs2/provider/res/ResourceFileNameParser.java  |  12 +-
 .../vfs2/provider/res/ResourceFileProvider.java    |  18 +-
 .../res/ResourceFileSystemConfigBuilder.java       |  20 +-
 .../commons/vfs2/provider/tar/TarFileObject.java   | 106 +--
 .../vfs2/provider/tar/Tbz2FileProvider.java        |   8 +-
 .../commons/vfs2/provider/tar/TgzFileProvider.java |   8 +-
 .../vfs2/provider/temp/TemporaryFileProvider.java  |  12 +-
 .../vfs2/provider/url/UrlFileNameParser.java       |  80 +-
 .../commons/vfs2/provider/url/UrlFileObject.java   |  72 +-
 .../commons/vfs2/provider/url/UrlFileProvider.java |   8 +-
 .../commons/vfs2/provider/url/UrlFileSystem.java   |  12 +-
 .../commons/vfs2/provider/zip/ZipFileObject.java   | 120 +--
 .../commons/vfs2/provider/zip/ZipFileSystem.java   | 128 +--
 .../commons/vfs2/tasks/AbstractSyncTask.java       | 290 +++----
 .../org/apache/commons/vfs2/tasks/CopyTask.java    |  58 +-
 .../org/apache/commons/vfs2/tasks/DeleteTask.java  |  54 +-
 .../org/apache/commons/vfs2/tasks/MkdirTask.java   |  18 +-
 .../org/apache/commons/vfs2/tasks/MoveTask.java    |  18 +-
 .../apache/commons/vfs2/tasks/ShowFileTask.java    |  74 +-
 .../org/apache/commons/vfs2/tasks/SyncTask.java    |  14 +-
 .../org/apache/commons/vfs2/tasks/VfsTask.java     | 160 ++--
 .../java/org/apache/commons/vfs2/util/Cryptor.java |  16 +-
 .../apache/commons/vfs2/util/CryptorFactory.java   |  18 +-
 .../apache/commons/vfs2/util/DefaultCryptor.java   |  90 +-
 .../util/DelegatingFileSystemOptionsBuilder.java   | 304 +++----
 .../commons/vfs2/util/MonitorInputStream.java      |  18 +-
 .../commons/vfs2/util/MonitorOutputStream.java     |  76 +-
 .../vfs2/util/MonitorRandomAccessContent.java      | 142 ++--
 .../main/java/org/apache/commons/vfs2/util/Os.java | 192 ++---
 .../org/apache/commons/vfs2/util/OsFamily.java     |  18 +-
 .../apache/commons/vfs2/util/RandomAccessMode.java |  36 +-
 .../commons/vfs2/util/RawMonitorInputStream.java   |  98 +--
 .../commons/vfs2/util/UserAuthenticatorUtils.java  |  66 +-
 .../commons/vfs2/util/WeakRefFileListener.java     |  40 +-
 .../commons/vfs2/AbstractProviderTestCase.java     |  22 +-
 .../vfs2/provider/ftp/FtpProviderTestCase.java     |  20 +-
 .../ftps/AbstractFtpsProviderTestCase.java         |   4 +-
 .../vfs2/provider/ram/RamProviderTestCase.java     |   4 +-
 .../sftp/AbstractSftpProviderTestCase.java         |  10 +-
 .../sftp/SftpPermissionExceptionTestCase.java      |  38 +-
 .../vfs2/provider/url/UrlProviderHttpTestCase.java |   8 +-
 .../apache/commons/vfs2/util/NHttpFileServer.java  |  22 +-
 143 files changed, 4766 insertions(+), 4766 deletions(-)

diff --git a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileObject.java b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileObject.java
index 19ec04b..a89cbab 100644
--- a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileObject.java
+++ b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileObject.java
@@ -80,11 +80,6 @@ import org.w3c.dom.Node;
 public class WebdavFileObject extends HttpFileObject<WebdavFileSystem> {
 
     /**
-     * An empty immutable {@code WebdavFileObject} array.
-     */
-    private static final WebdavFileObject[] EMPTY_ARRAY = {};
-
-    /**
      * An OutputStream that writes to a Webdav resource.
      * <p>
      * TODO - Use piped stream to avoid temporary file.
@@ -216,6 +211,11 @@ public class WebdavFileObject extends HttpFileObject<WebdavFileSystem> {
         }
     }
 
+    /**
+     * An empty immutable {@code WebdavFileObject} array.
+     */
+    private static final WebdavFileObject[] EMPTY_ARRAY = {};
+
     /** The character set property name. */
     public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create("response-charset");
 
@@ -230,10 +230,6 @@ public class WebdavFileObject extends HttpFileObject<WebdavFileSystem> {
         builder = (WebdavFileSystemConfigBuilder) WebdavFileSystemConfigBuilder.getInstance();
     }
 
-    void log(final Exception ex) {
-        // TODO Consider logging.
-    }
-
     protected void configureMethod(final HttpMethodBase httpMethod) {
         httpMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, WebdavMethodRetryHandler.getInstance());
     }
@@ -575,6 +571,10 @@ public class WebdavFileObject extends HttpFileObject<WebdavFileSystem> {
         }
     }
 
+    void log(final Exception ex) {
+        // TODO Consider logging.
+    }
+
     /**
      * Returns the resource name from the path.
      *
diff --git a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileProvider.java b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileProvider.java
index 37a557b..2d01afb 100644
--- a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileProvider.java
+++ b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileProvider.java
@@ -99,12 +99,12 @@ public class WebdavFileProvider extends HttpFileProvider {
     }
 
     @Override
-    public FileSystemConfigBuilder getConfigBuilder() {
-        return WebdavFileSystemConfigBuilder.getInstance();
+    public Collection<Capability> getCapabilities() {
+        return capabilities;
     }
 
     @Override
-    public Collection<Capability> getCapabilities() {
-        return capabilities;
+    public FileSystemConfigBuilder getConfigBuilder() {
+        return WebdavFileSystemConfigBuilder.getInstance();
     }
 }
diff --git a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystem.java b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystem.java
index 538ffac..03bba68 100644
--- a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystem.java
+++ b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystem.java
@@ -40,12 +40,6 @@ public class WebdavFileSystem extends HttpFileSystem {
         super(rootName, client, fileSystemOptions);
     }
 
-    @Override
-    protected HttpClient getClient() {
-        // make accessible
-        return super.getClient();
-    }
-
     /**
      * Returns the capabilities of this file system.
      *
@@ -68,6 +62,12 @@ public class WebdavFileSystem extends HttpFileSystem {
         return new WebdavFileObject(name, this);
     }
 
+    @Override
+    protected HttpClient getClient() {
+        // make accessible
+        return super.getClient();
+    }
+
     /**
      * Return a URLStreamHandler.
      *
diff --git a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystemConfigBuilder.java b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystemConfigBuilder.java
index a86fa45..4c33a2b 100644
--- a/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystemConfigBuilder.java
+++ b/commons-vfs2-jackrabbit1/src/main/java/org/apache/commons/vfs2/provider/webdav/WebdavFileSystemConfigBuilder.java
@@ -45,13 +45,11 @@ public final class WebdavFileSystemConfigBuilder extends HttpFileSystemConfigBui
     }
 
     /**
-     * The user name to be associated with changes to the file.
-     *
-     * @param opts The FileSystem options
-     * @param creatorName The creator name to be associated with the file.
+     * @return The Webdav FileSystem Class object.
      */
-    public void setCreatorName(final FileSystemOptions opts, final String creatorName) {
-        setParam(opts, "creatorName", creatorName);
+    @Override
+    protected Class<? extends FileSystem> getConfigClass() {
+        return WebdavFileSystem.class;
     }
 
     /**
@@ -78,30 +76,32 @@ public final class WebdavFileSystemConfigBuilder extends HttpFileSystemConfigBui
     }
 
     /**
-     * Whether to use versioning.
+     * The cookies to add to the request.
      *
      * @param opts The FileSystem options.
-     * @param versioning true if versioning should be enabled.
+     * @return true if versioning is enabled.
      */
-    public void setVersioning(final FileSystemOptions opts, final boolean versioning) {
-        setParam(opts, "versioning", Boolean.valueOf(versioning));
+    public boolean isVersioning(final FileSystemOptions opts) {
+        return getBoolean(opts, "versioning", false);
     }
 
     /**
-     * The cookies to add to the request.
+     * The user name to be associated with changes to the file.
      *
-     * @param opts The FileSystem options.
-     * @return true if versioning is enabled.
+     * @param opts The FileSystem options
+     * @param creatorName The creator name to be associated with the file.
      */
-    public boolean isVersioning(final FileSystemOptions opts) {
-        return getBoolean(opts, "versioning", false);
+    public void setCreatorName(final FileSystemOptions opts, final String creatorName) {
+        setParam(opts, "creatorName", creatorName);
     }
 
     /**
-     * @return The Webdav FileSystem Class object.
+     * Whether to use versioning.
+     *
+     * @param opts The FileSystem options.
+     * @param versioning true if versioning should be enabled.
      */
-    @Override
-    protected Class<? extends FileSystem> getConfigClass() {
-        return WebdavFileSystem.class;
+    public void setVersioning(final FileSystemOptions opts, final boolean versioning) {
+        setParam(opts, "versioning", Boolean.valueOf(versioning));
     }
 }
diff --git a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JackrabbitMain.java b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JackrabbitMain.java
index 3e278c6..94e886c 100644
--- a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JackrabbitMain.java
+++ b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JackrabbitMain.java
@@ -54,13 +54,6 @@ import org.mortbay.jetty.webapp.WebAppContext;
  */
 class JackrabbitMain {
 
-    /**
-     * @param args
-     */
-    public static void main(final String[] args) throws Exception {
-        new JackrabbitMain(args).run();
-    }
-
     private final Options options = new Options();
 
     private final CommandLine command;
@@ -74,8 +67,8 @@ class JackrabbitMain {
     private final Server server = new Server();
 
     private FileAppender jackrabbitAppender;
-    private FileAppender jettyAppender;
 
+    private FileAppender jettyAppender;
     public JackrabbitMain(final String[] args) throws ParseException {
         options.addOption("?", "help", false, "print this message");
         options.addOption("n", "notice", false, "print copyright notices");
@@ -93,12 +86,28 @@ class JackrabbitMain {
         command = new GnuParser().parse(options, args);
     }
 
+    /**
+     * @param args
+     */
+    public static void main(final String[] args) throws Exception {
+        new JackrabbitMain(args).run();
+    }
+
     private void copyToOutput(final String resource) throws IOException {
         try (InputStream stream = JackrabbitMain.class.getResourceAsStream(resource)) {
             IOUtils.copy(stream, System.out);
         }
     }
 
+    /** Try to load a resource with various classloaders. */
+    private URL getResource(final String name) {
+        URL res = Thread.currentThread().getContextClassLoader().getResource(name);
+        if (res == null) {
+            res = getClass().getResource(name);
+        }
+        return res; // might be null
+    }
+
     private void message(final String message) {
         if (!command.hasOption("quiet")) {
             System.out.println(message);
@@ -173,15 +182,6 @@ class JackrabbitMain {
         webapp.addServlet(servlet, "/repository.properties");
     }
 
-    /** Try to load a resource with various classloaders. */
-    private URL getResource(final String name) {
-        URL res = Thread.currentThread().getContextClassLoader().getResource(name);
-        if (res == null) {
-            res = getClass().getResource(name);
-        }
-        return res; // might be null
-    }
-
     public void run() throws Exception {
         String defaultFile = "jackrabbit-standalone.jar";
         final URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
diff --git a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JcrUtils.java b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JcrUtils.java
index 4420ef9..2438254 100644
--- a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JcrUtils.java
+++ b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/JcrUtils.java
@@ -52,6 +52,12 @@ class JcrUtils {
     private static final String Property_JCR_DATA = "jcr:data";
 
     /**
+     * Private constructor to prevent instantiation of this class.
+     */
+    private JcrUtils() {
+    }
+
+    /**
      * Returns the named child of the given node, creating it as an nt:folder node if it does not already exist. The
      * caller is expected to take care of saving or discarding any transient changes.
      * <p>
@@ -185,10 +191,4 @@ class JcrUtils {
             // binary.dispose();
         }
     }
-
-    /**
-     * Private constructor to prevent instantiation of this class.
-     */
-    private JcrUtils() {
-    }
 }
diff --git a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavProviderTestCase.java b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavProviderTestCase.java
index a2f086b..099752d 100644
--- a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavProviderTestCase.java
+++ b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavProviderTestCase.java
@@ -71,6 +71,14 @@ public class WebdavProviderTestCase extends AbstractProviderTestConfig {
 
     private static final boolean DEBUG = Boolean.getBoolean("WebdavProviderTestCase.Debug");
 
+    public WebdavProviderTestCase() throws IOException {
+        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
+        message("FreeSocketPortUtil.findFreeLocalPort() = " + SocketPort);
+        // Use %40 for @ in a URL
+        // Any user id and password will do with the default Jackrabbit set up.
+        ConnectionUri = String.format("webdav://%s@localhost:%d/repository/default", USER_ID, SocketPort);
+    }
+
     static File createTempDirectory() throws IOException {
         // create base folder
         final File base = new File("./target/test").getCanonicalFile();
@@ -280,14 +288,6 @@ public class WebdavProviderTestCase extends AbstractProviderTestConfig {
         }
     }
 
-    public WebdavProviderTestCase() throws IOException {
-        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
-        message("FreeSocketPortUtil.findFreeLocalPort() = " + SocketPort);
-        // Use %40 for @ in a URL
-        // Any user id and password will do with the default Jackrabbit set up.
-        ConnectionUri = String.format("webdav://%s@localhost:%d/repository/default", USER_ID, SocketPort);
-    }
-
     /**
      * Returns the base folder for tests.
      */
diff --git a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavVersioningTests.java b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavVersioningTests.java
index c1b279d..ed8b676 100644
--- a/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavVersioningTests.java
+++ b/commons-vfs2-jackrabbit1/src/test/java/org/apache/commons/vfs2/provider/webdav/test/WebdavVersioningTests.java
@@ -36,6 +36,19 @@ import org.junit.Test;
  */
 public class WebdavVersioningTests extends AbstractProviderTestCase {
 
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception {
+        final FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
     @Test
     public void testVersioning() throws Exception {
         final FileObject scratchFolder = createScratchFolder();
@@ -134,17 +147,4 @@ public class WebdavVersioningTests extends AbstractProviderTestCase {
         builder.setCreatorName(opts, null);
     }
 
-    /**
-     * Sets up a scratch folder for the test to use.
-     */
-    protected FileObject createScratchFolder() throws Exception {
-        final FileObject scratchFolder = getWriteFolder();
-
-        // Make sure the test folder is empty
-        scratchFolder.delete(Selectors.EXCLUDE_SELF);
-        scratchFolder.createFolder();
-
-        return scratchFolder;
-    }
-
 }
diff --git a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileObject.java b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileObject.java
index 9da008d..4345cd3 100644
--- a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileObject.java
+++ b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileObject.java
@@ -80,11 +80,6 @@ import org.w3c.dom.Node;
 public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> {
 
     /**
-     * An empty immutable {@code Webdav4FileObject} array.
-     */
-    private static final Webdav4FileObject[] EMPTY_ARRAY = {};
-
-    /**
      * An OutputStream that writes to a Webdav resource.
      * <p>
      * TODO - Use piped stream to avoid temporary file.
@@ -216,6 +211,11 @@ public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> {
         }
     }
 
+    /**
+     * An empty immutable {@code Webdav4FileObject} array.
+     */
+    private static final Webdav4FileObject[] EMPTY_ARRAY = {};
+
     /** The character set property name. */
     public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create("response-charset");
 
@@ -228,10 +228,6 @@ public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> {
         this(name, fileSystem, Webdav4FileSystemConfigBuilder.getInstance());
     }
 
-    void log(final Exception ex) {
-        // TODO Consider logging
-    }
-
     protected Webdav4FileObject(final AbstractFileName name, final Webdav4FileSystem fileSystem,
             final Webdav4FileSystemConfigBuilder builder) throws FileSystemException {
         super(name, fileSystem, builder);
@@ -577,6 +573,10 @@ public class Webdav4FileObject extends Http4FileObject<Webdav4FileSystem> {
         }
     }
 
+    void log(final Exception ex) {
+        // TODO Consider logging
+    }
+
     /**
      * Returns the resource name from the path.
      *
diff --git a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileProvider.java b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileProvider.java
index d0e5cb6..7397f20 100644
--- a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileProvider.java
+++ b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileProvider.java
@@ -111,12 +111,12 @@ public class Webdav4FileProvider extends Http4FileProvider {
     }
 
     @Override
-    public FileSystemConfigBuilder getConfigBuilder() {
-        return Webdav4FileSystemConfigBuilder.getInstance();
+    public Collection<Capability> getCapabilities() {
+        return capabilities;
     }
 
     @Override
-    public Collection<Capability> getCapabilities() {
-        return capabilities;
+    public FileSystemConfigBuilder getConfigBuilder() {
+        return Webdav4FileSystemConfigBuilder.getInstance();
     }
 }
diff --git a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileSystemConfigBuilder.java b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileSystemConfigBuilder.java
index 6b1ae95..05ddf55 100644
--- a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileSystemConfigBuilder.java
+++ b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4/Webdav4FileSystemConfigBuilder.java
@@ -45,13 +45,11 @@ public final class Webdav4FileSystemConfigBuilder extends Http4FileSystemConfigB
     }
 
     /**
-     * The user name to be associated with changes to the file.
-     *
-     * @param opts The FileSystem options
-     * @param creatorName The creator name to be associated with the file.
+     * @return The Webdav FileSystem Class object.
      */
-    public void setCreatorName(final FileSystemOptions opts, final String creatorName) {
-        setParam(opts, "creatorName", creatorName);
+    @Override
+    protected Class<? extends FileSystem> getConfigClass() {
+        return Webdav4FileSystem.class;
     }
 
     /**
@@ -77,30 +75,32 @@ public final class Webdav4FileSystemConfigBuilder extends Http4FileSystemConfigB
     }
 
     /**
-     * Whether to use versioning.
+     * The cookies to add to the request.
      *
      * @param opts The FileSystem options.
-     * @param versioning true if versioning should be enabled.
+     * @return true if versioning is enabled.
      */
-    public void setVersioning(final FileSystemOptions opts, final boolean versioning) {
-        setParam(opts, "versioning", Boolean.valueOf(versioning));
+    public boolean isVersioning(final FileSystemOptions opts) {
+        return getBoolean(opts, "versioning", false);
     }
 
     /**
-     * The cookies to add to the request.
+     * The user name to be associated with changes to the file.
      *
-     * @param opts The FileSystem options.
-     * @return true if versioning is enabled.
+     * @param opts The FileSystem options
+     * @param creatorName The creator name to be associated with the file.
      */
-    public boolean isVersioning(final FileSystemOptions opts) {
-        return getBoolean(opts, "versioning", false);
+    public void setCreatorName(final FileSystemOptions opts, final String creatorName) {
+        setParam(opts, "creatorName", creatorName);
     }
 
     /**
-     * @return The Webdav FileSystem Class object.
+     * Whether to use versioning.
+     *
+     * @param opts The FileSystem options.
+     * @param versioning true if versioning should be enabled.
      */
-    @Override
-    protected Class<? extends FileSystem> getConfigClass() {
-        return Webdav4FileSystem.class;
+    public void setVersioning(final FileSystemOptions opts, final boolean versioning) {
+        setParam(opts, "versioning", Boolean.valueOf(versioning));
     }
 }
diff --git a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4s/Webdav4sFileProvider.java b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4s/Webdav4sFileProvider.java
index 0535396..bcb973f 100644
--- a/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4s/Webdav4sFileProvider.java
+++ b/commons-vfs2-jackrabbit2/src/main/java/org/apache/commons/vfs2/provider/webdav4s/Webdav4sFileProvider.java
@@ -85,13 +85,13 @@ public class Webdav4sFileProvider extends Http4sFileProvider {
     }
 
     @Override
-    public FileSystemConfigBuilder getConfigBuilder() {
-        return Webdav4FileSystemConfigBuilder.getInstance();
+    public Collection<Capability> getCapabilities() {
+        return capabilities;
     }
 
     @Override
-    public Collection<Capability> getCapabilities() {
-        return capabilities;
+    public FileSystemConfigBuilder getConfigBuilder() {
+        return Webdav4FileSystemConfigBuilder.getInstance();
     }
 
 }
diff --git a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/JcrUtils.java b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/JcrUtils.java
index ea24569..f09b1fd 100644
--- a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/JcrUtils.java
+++ b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/JcrUtils.java
@@ -52,6 +52,12 @@ class JcrUtils {
     private static final String Property_JCR_DATA = "jcr:data";
 
     /**
+     * Private constructor to prevent instantiation of this class.
+     */
+    private JcrUtils() {
+    }
+
+    /**
      * Returns the named child of the given node, creating it as an nt:folder node if it does not already exist. The
      * caller is expected to take care of saving or discarding any transient changes.
      * <p>
@@ -186,10 +192,4 @@ class JcrUtils {
             // binary.dispose();
         }
     }
-
-    /**
-     * Private constructor to prevent instantiation of this class.
-     */
-    private JcrUtils() {
-    }
 }
diff --git a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4ProviderTestCase.java b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4ProviderTestCase.java
index b411e03..aaded83 100644
--- a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4ProviderTestCase.java
+++ b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4ProviderTestCase.java
@@ -75,6 +75,14 @@ public class Webdav4ProviderTestCase extends AbstractProviderTestConfig {
 
     private static final boolean DEBUG = Boolean.getBoolean("Webdav4ProviderTestCase.Debug");
 
+    public Webdav4ProviderTestCase() throws IOException {
+        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
+        message("FreeSocketPortUtil.findFreeLocalPort() = " + SocketPort);
+        // Use %40 for @ in a URL
+        // Any user id and password will do with the default Jackrabbit set up.
+        ConnectionUri = String.format("webdav4://%s:%s@localhost:%d/repository/default", USER_ID, PASSWORD, SocketPort);
+    }
+
     static File createTempDirectory() throws IOException {
         // create base folder
         final File base = new File("./target/test").getCanonicalFile();
@@ -289,14 +297,6 @@ public class Webdav4ProviderTestCase extends AbstractProviderTestConfig {
         }
     }
 
-    public Webdav4ProviderTestCase() throws IOException {
-        SocketPort = FreeSocketPortUtil.findFreeLocalPort();
-        message("FreeSocketPortUtil.findFreeLocalPort() = " + SocketPort);
-        // Use %40 for @ in a URL
-        // Any user id and password will do with the default Jackrabbit set up.
-        ConnectionUri = String.format("webdav4://%s:%s@localhost:%d/repository/default", USER_ID, PASSWORD, SocketPort);
-    }
-
     /**
      * Returns the base folder for tests.
      */
diff --git a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4VersioningTests.java b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4VersioningTests.java
index e5b60c6..3f9502b 100644
--- a/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4VersioningTests.java
+++ b/commons-vfs2-jackrabbit2/src/test/java/org/apache/commons/vfs2/provider/webdav4/test/Webdav4VersioningTests.java
@@ -38,6 +38,19 @@ import org.junit.Test;
  */
 public class Webdav4VersioningTests extends AbstractProviderTestCase {
 
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception {
+        final FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
     @Test
     public void testVersioning() throws Exception {
         final FileObject scratchFolder = createScratchFolder();
@@ -136,17 +149,4 @@ public class Webdav4VersioningTests extends AbstractProviderTestCase {
         builder.setCreatorName(opts, null);
     }
 
-    /**
-     * Sets up a scratch folder for the test to use.
-     */
-    protected FileObject createScratchFolder() throws Exception {
-        final FileObject scratchFolder = getWriteFolder();
-
-        // Make sure the test folder is empty
-        scratchFolder.delete(Selectors.EXCLUDE_SELF);
-        scratchFolder.createFolder();
-
-        return scratchFolder;
-    }
-
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/CacheStrategy.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/CacheStrategy.java
index 960ab10..a69b390 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/CacheStrategy.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/CacheStrategy.java
@@ -51,8 +51,7 @@ public enum CacheStrategy {
      *
      * @return the name of the scope.
      */
-    @Override
-    public String toString() {
+    public String getName() {
         return realName;
     }
 
@@ -61,7 +60,8 @@ public enum CacheStrategy {
      *
      * @return the name of the scope.
      */
-    public String getName() {
+    @Override
+    public String toString() {
         return realName;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileDepthSelector.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileDepthSelector.java
index dd81c97..8851731 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileDepthSelector.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileDepthSelector.java
@@ -26,13 +26,12 @@ public class FileDepthSelector implements FileSelector {
     private final Range<Integer> range;
 
     /**
-     * Creates a selector with the given minimum and maximum depths.
+     * Creates a selector with the same minimum and maximum depths of 0.
      *
-     * @param minDepth minimum depth
-     * @param maxDepth maximum depth
+     * @since 2.1
      */
-    public FileDepthSelector(final int minDepth, final int maxDepth) {
-        this.range = Range.between(minDepth, maxDepth);
+    public FileDepthSelector() {
+        this(0, 0);
     }
 
     /**
@@ -46,12 +45,13 @@ public class FileDepthSelector implements FileSelector {
     }
 
     /**
-     * Creates a selector with the same minimum and maximum depths of 0.
+     * Creates a selector with the given minimum and maximum depths.
      *
-     * @since 2.1
+     * @param minDepth minimum depth
+     * @param maxDepth maximum depth
      */
-    public FileDepthSelector() {
-        this(0, 0);
+    public FileDepthSelector(final int minDepth, final int maxDepth) {
+        this.range = Range.between(minDepth, maxDepth);
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileFilterSelector.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileFilterSelector.java
index c0946ab..ce3ebb1 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileFilterSelector.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileFilterSelector.java
@@ -48,17 +48,6 @@ public class FileFilterSelector extends FileDepthSelector {
     }
 
     /**
-     * Determines if a file or folder should be selected.
-     *
-     * @param fileInfo The file selection information.
-     * @return true if the file or folder should be included, false otherwise.
-     */
-    @Override
-    public boolean includeFile(final FileSelectInfo fileInfo) throws Exception {
-        return super.includeFile(fileInfo) && accept(fileInfo);
-    }
-
-    /**
      * Determines whether the file should be selected.
      *
      * @param fileInfo The file selection information.
@@ -72,4 +61,15 @@ public class FileFilterSelector extends FileDepthSelector {
 
         throw new IllegalArgumentException(Messages.getString("vfs.selectors/filefilter.missing.error"));
     }
+
+    /**
+     * Determines if a file or folder should be selected.
+     *
+     * @param fileInfo The file selection information.
+     * @return true if the file or folder should be included, false otherwise.
+     */
+    @Override
+    public boolean includeFile(final FileSelectInfo fileInfo) throws Exception {
+        return super.includeFile(fileInfo) && accept(fileInfo);
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileListener.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileListener.java
index 981a2de..ea5d4c1 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileListener.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileListener.java
@@ -22,29 +22,29 @@ package org.apache.commons.vfs2;
 public interface FileListener {
 
     /**
-     * Called when a file is created.
+     * Called when a file is changed.
+     * <p>
+     * This will only happen if you monitor the file using {@link FileMonitor}.
+     * </p>
      *
      * @param event The FileChangeEvent.
      * @throws Exception if an error occurs.
      */
-    void fileCreated(FileChangeEvent event) throws Exception;
+    void fileChanged(FileChangeEvent event) throws Exception;
 
     /**
-     * Called when a file is deleted.
+     * Called when a file is created.
      *
      * @param event The FileChangeEvent.
      * @throws Exception if an error occurs.
      */
-    void fileDeleted(FileChangeEvent event) throws Exception;
+    void fileCreated(FileChangeEvent event) throws Exception;
 
     /**
-     * Called when a file is changed.
-     * <p>
-     * This will only happen if you monitor the file using {@link FileMonitor}.
-     * </p>
+     * Called when a file is deleted.
      *
      * @param event The FileChangeEvent.
      * @throws Exception if an error occurs.
      */
-    void fileChanged(FileChangeEvent event) throws Exception;
+    void fileDeleted(FileChangeEvent event) throws Exception;
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileObject.java
index 3c390da..db50aab 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileObject.java
@@ -286,6 +286,16 @@ public interface FileObject extends Comparable<FileObject>, Iterable<FileObject>
     FileObject getParent() throws FileSystemException;
 
     /**
+     * Returns a Path representing this file.
+     *
+     * @return the Path for the file.
+     * @since 2.7.0
+     */
+    default Path getPath() {
+        return Paths.get(getURI());
+    }
+
+    /**
      * Returns the receiver as a URI String for public display, like, without a password.
      *
      * @return A URI String without a password, never {@code null}.
@@ -311,16 +321,6 @@ public interface FileObject extends Comparable<FileObject>, Iterable<FileObject>
     }
 
     /**
-     * Returns a Path representing this file.
-     *
-     * @return the Path for the file.
-     * @since 2.7.0
-     */
-    default Path getPath() {
-        return Paths.get(getURI());
-    }
-
-    /**
      * Returns a URL representing this file.
      *
      * @return the URL for the file.
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSelectInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSelectInfo.java
index 7c10e5e..fac5348 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSelectInfo.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSelectInfo.java
@@ -32,16 +32,16 @@ public interface FileSelectInfo {
     FileObject getBaseFolder();
 
     /**
-     * Returns the file (or folder) to be considered.
+     * Returns the depth of the file relative to the base folder.
      *
-     * @return The FileObject.
+     * @return The depth of the file relative to the base folder.
      */
-    FileObject getFile();
+    int getDepth();
 
     /**
-     * Returns the depth of the file relative to the base folder.
+     * Returns the file (or folder) to be considered.
      *
-     * @return The depth of the file relative to the base folder.
+     * @return The FileObject.
      */
-    int getDepth();
+    FileObject getFile();
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystem.java
index 7c817d9..cb839f7 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystem.java
@@ -24,46 +24,23 @@ import java.io.File;
 public interface FileSystem {
 
     /**
-     * Returns the root file of this file system.
-     *
-     * @return The root FileObject.
-     * @throws FileSystemException if an error occurs.
-     */
-    FileObject getRoot() throws FileSystemException;
-
-    /**
-     * Returns the name of the root file of this file system. The root name always contains a path String of "/".
-     *
-     * @return the root FileName.
-     */
-    FileName getRootName();
-
-    /**
-     * The root URI passed as a file system option or obtained from the rootName.
-     *
-     * @return The root URI.
-     */
-    String getRootURI();
-
-    /**
-     * Determines if this file system has a particular capability.
-     * <p>
-     * TODO - Move this to another interface, so that set of capabilities can be queried.
-     * </p>
+     * Adds a junction to this file system. A junction is a link that attaches the supplied file to a point in this file
+     * system, making it look like part of the file system.
      *
-     * @param capability The capability to check for.
-     * @return true if this file system has the requested capability. Note that not all files in the file system may have
-     *         the capability.
+     * @param junctionPoint The point in this file system to add the junction.
+     * @param targetFile The file to link to.
+     * @throws FileSystemException If this file system does not support junctions, or the junction point or target file
+     *             is invalid (the file system may not support nested junctions, for example).
      */
-    boolean hasCapability(Capability capability);
+    void addJunction(String junctionPoint, FileObject targetFile) throws FileSystemException;
 
     /**
-     * Returns the parent layer if this is a layered file system.
+     * Adds a listener on a file in this file system.
      *
-     * @return The parent layer, or null if this is not a layered file system.
-     * @throws FileSystemException if an error occurs.
+     * @param file The file to attach the listener to.
+     * @param listener The listener to add.
      */
-    FileObject getParentLayer() throws FileSystemException;
+    void addListener(FileObject file, FileListener listener);
 
     /**
      * Gets the value of an attribute of the file system.
@@ -83,60 +60,73 @@ public interface FileSystem {
     Object getAttribute(String attrName) throws FileSystemException;
 
     /**
-     * Sets the value of an attribute of the file's content. Creates the file if it does not exist.
+     * Returns a reference to the FileSytemManager.
      *
-     * @param attrName The name of the attribute.
-     * @param value The value of the attribute.
-     * @throws FileSystemException If the file is read-only, or is being read, or if the attribute is not supported, or
-     *             on error setting the attribute.
-     * @see FileContent#setAttribute
+     * @return The FileSystemManager.
      */
-    void setAttribute(String attrName, Object value) throws FileSystemException;
+    FileSystemManager getFileSystemManager();
 
     /**
-     * Finds a file in this file system.
+     * Returns the FileSystemOptions used to instantiate this file system.
      *
-     * @param name The name of the file.
-     * @return The file. Never returns null.
+     * @return The FileSystemOptions.
+     */
+    FileSystemOptions getFileSystemOptions();
+
+    /**
+     * Returns the accuracy of the last modification time in milliseconds.
+     * <p>
+     * The local file provider is not very smart in figuring this out, for remote access to file systems the providers
+     * typically don't know the value of the underlying real file system.
+     * </p>
+     *
+     * @return the accuracy of the last modification time in milliseconds. A value of 0 means perfectly accurate,
+     *         anything {@literal > 0} might be off by this value. For example, sftp has an accuracy of 1000
+     *         milliseconds.
+     */
+    double getLastModTimeAccuracy();
+
+    /**
+     * Returns the parent layer if this is a layered file system.
+     *
+     * @return The parent layer, or null if this is not a layered file system.
      * @throws FileSystemException if an error occurs.
      */
-    FileObject resolveFile(FileName name) throws FileSystemException;
+    FileObject getParentLayer() throws FileSystemException;
 
     /**
-     * Finds a file in this file system.
+     * Returns the root file of this file system.
      *
-     * @param name The name of the file. This must be an absolute path.
-     * @return The file. Never returns null.
+     * @return The root FileObject.
      * @throws FileSystemException if an error occurs.
      */
-    FileObject resolveFile(String name) throws FileSystemException;
+    FileObject getRoot() throws FileSystemException;
 
     /**
-     * Adds a listener on a file in this file system.
+     * Returns the name of the root file of this file system. The root name always contains a path String of "/".
      *
-     * @param file The file to attach the listener to.
-     * @param listener The listener to add.
+     * @return the root FileName.
      */
-    void addListener(FileObject file, FileListener listener);
+    FileName getRootName();
 
     /**
-     * Removes a listener from a file in this file system.
+     * The root URI passed as a file system option or obtained from the rootName.
      *
-     * @param file The file to remove the listener from.
-     * @param listener The listener to remove.
+     * @return The root URI.
      */
-    void removeListener(FileObject file, FileListener listener);
+    String getRootURI();
 
     /**
-     * Adds a junction to this file system. A junction is a link that attaches the supplied file to a point in this file
-     * system, making it look like part of the file system.
+     * Determines if this file system has a particular capability.
+     * <p>
+     * TODO - Move this to another interface, so that set of capabilities can be queried.
+     * </p>
      *
-     * @param junctionPoint The point in this file system to add the junction.
-     * @param targetFile The file to link to.
-     * @throws FileSystemException If this file system does not support junctions, or the junction point or target file
-     *             is invalid (the file system may not support nested junctions, for example).
+     * @param capability The capability to check for.
+     * @return true if this file system has the requested capability. Note that not all files in the file system may have
+     *         the capability.
      */
-    void addJunction(String junctionPoint, FileObject targetFile) throws FileSystemException;
+    boolean hasCapability(Capability capability);
 
     /**
      * Removes a junction from this file system.
@@ -147,6 +137,14 @@ public interface FileSystem {
     void removeJunction(String junctionPoint) throws FileSystemException;
 
     /**
+     * Removes a listener from a file in this file system.
+     *
+     * @param file The file to remove the listener from.
+     * @param listener The listener to remove.
+     */
+    void removeListener(FileObject file, FileListener listener);
+
+    /**
      * Creates a temporary local copy of a file and its descendants. If this file is already a local file, a copy is not
      * made.
      * <p>
@@ -165,29 +163,31 @@ public interface FileSystem {
     File replicateFile(FileObject file, FileSelector selector) throws FileSystemException;
 
     /**
-     * Returns the FileSystemOptions used to instantiate this file system.
+     * Finds a file in this file system.
      *
-     * @return The FileSystemOptions.
+     * @param name The name of the file.
+     * @return The file. Never returns null.
+     * @throws FileSystemException if an error occurs.
      */
-    FileSystemOptions getFileSystemOptions();
+    FileObject resolveFile(FileName name) throws FileSystemException;
 
     /**
-     * Returns a reference to the FileSytemManager.
+     * Finds a file in this file system.
      *
-     * @return The FileSystemManager.
+     * @param name The name of the file. This must be an absolute path.
+     * @return The file. Never returns null.
+     * @throws FileSystemException if an error occurs.
      */
-    FileSystemManager getFileSystemManager();
+    FileObject resolveFile(String name) throws FileSystemException;
 
     /**
-     * Returns the accuracy of the last modification time in milliseconds.
-     * <p>
-     * The local file provider is not very smart in figuring this out, for remote access to file systems the providers
-     * typically don't know the value of the underlying real file system.
-     * </p>
+     * Sets the value of an attribute of the file's content. Creates the file if it does not exist.
      *
-     * @return the accuracy of the last modification time in milliseconds. A value of 0 means perfectly accurate,
-     *         anything {@literal > 0} might be off by this value. For example, sftp has an accuracy of 1000
-     *         milliseconds.
+     * @param attrName The name of the attribute.
+     * @param value The value of the attribute.
+     * @throws FileSystemException If the file is read-only, or is being read, or if the attribute is not supported, or
+     *             on error setting the attribute.
+     * @see FileContent#setAttribute
      */
-    double getLastModTimeAccuracy();
+    void setAttribute(String attrName, Object value) throws FileSystemException;
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemException.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemException.java
index bd9b1b7..2c62421 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemException.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemException.java
@@ -64,17 +64,6 @@ public class FileSystemException extends IOException {
     }
 
     /**
-     * Constructs exception with the specified detail message and cause.
-     *
-     * @param code the error code of the message.
-     * @param info one context information.
-     * @param cause the cause.
-     */
-    public FileSystemException(final String code, final Object info, final Throwable cause) {
-        this(code, cause, new Object[] {info});
-    }
-
-    /**
      * Constructs exception with the specified detail message.
      *
      * @param code the error code of the message.
@@ -85,13 +74,14 @@ public class FileSystemException extends IOException {
     }
 
     /**
-     * Constructs exception with the specified detail message.
+     * Constructs exception with the specified detail message and cause.
      *
      * @param code the error code of the message.
-     * @param cause the original cause
+     * @param info one context information.
+     * @param cause the cause.
      */
-    public FileSystemException(final String code, final Throwable cause) {
-        this(code, cause, (Object[]) null);
+    public FileSystemException(final String code, final Object info, final Throwable cause) {
+        this(code, cause, new Object[] {info});
     }
 
     /**
@@ -111,6 +101,16 @@ public class FileSystemException extends IOException {
      * Constructs exception with the specified detail message.
      *
      * @param code the error code of the message.
+     * @param cause the original cause
+     */
+    public FileSystemException(final String code, final Throwable cause) {
+        this(code, cause, (Object[]) null);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code the error code of the message.
      * @param info array of complementary info (context).
      * @param cause the cause.
      */
@@ -189,16 +189,6 @@ public class FileSystemException extends IOException {
     }
 
     /**
-     * Retrieves message from bundle.
-     *
-     * @return The exception message.
-     */
-    @Override
-    public String getMessage() {
-        return Messages.getString(super.getMessage(), (Object[]) getInfo());
-    }
-
-    /**
      * Retrieves error code of the exception. Could be used as key for internationalization.
      *
      * @return the code.
@@ -215,4 +205,14 @@ public class FileSystemException extends IOException {
     public String[] getInfo() {
         return info;
     }
+
+    /**
+     * Retrieves message from bundle.
+     *
+     * @return The exception message.
+     */
+    @Override
+    public String getMessage() {
+        return Messages.getString(super.getMessage(), (Object[]) getInfo());
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemOptions.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemOptions.java
index 4ba1c0e..1daf299 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemOptions.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileSystemOptions.java
@@ -46,20 +46,6 @@ import java.util.TreeMap;
  */
 public final class FileSystemOptions implements Cloneable, Comparable<FileSystemOptions> {
 
-    /** The options */
-    private final Map<FileSystemOptionKey, Object> options;
-
-    /**
-     * Constructs a new instance.
-     */
-    public FileSystemOptions() {
-        this(new TreeMap<>());
-    }
-
-    protected FileSystemOptions(final Map<FileSystemOptionKey, Object> options) {
-        this.options = options;
-    }
-
     /**
      * Keys in the options Map.
      */
@@ -120,18 +106,28 @@ public final class FileSystemOptions implements Cloneable, Comparable<FileSystem
         }
     }
 
-    void setOption(final Class<? extends FileSystem> fileSystemClass, final String name, final Object value) {
-        options.put(new FileSystemOptionKey(fileSystemClass, name), value);
+    /** The options */
+    private final Map<FileSystemOptionKey, Object> options;
+
+    /**
+     * Constructs a new instance.
+     */
+    public FileSystemOptions() {
+        this(new TreeMap<>());
     }
 
-    <T> T getOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
-        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
-        return (T) options.get(key);
+    protected FileSystemOptions(final Map<FileSystemOptionKey, Object> options) {
+        this.options = options;
     }
 
-    boolean hasOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
-        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
-        return options.containsKey(key);
+    /**
+     * {@inheritDoc}
+     *
+     * @since 2.0
+     */
+    @Override
+    public Object clone() {
+        return new FileSystemOptions(new TreeMap<>(options));
     }
 
     @Override
@@ -178,6 +174,26 @@ public final class FileSystemOptions implements Cloneable, Comparable<FileSystem
     }
 
     @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final FileSystemOptions other = (FileSystemOptions) obj;
+        return compareTo(other) == 0;
+    }
+
+    <T> T getOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
+        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
+        return (T) options.get(key);
+    }
+
+    @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
@@ -193,29 +209,13 @@ public final class FileSystemOptions implements Cloneable, Comparable<FileSystem
         return result;
     }
 
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (getClass() != obj.getClass()) {
-            return false;
-        }
-        final FileSystemOptions other = (FileSystemOptions) obj;
-        return compareTo(other) == 0;
+    boolean hasOption(final Class<? extends FileSystem> fileSystemClass, final String name) {
+        final FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
+        return options.containsKey(key);
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * @since 2.0
-     */
-    @Override
-    public Object clone() {
-        return new FileSystemOptions(new TreeMap<>(options));
+    void setOption(final Class<? extends FileSystem> fileSystemClass, final String name, final Object value) {
+        options.put(new FileSystemOptionKey(fileSystemClass, name), value);
     }
 
     @Override
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileType.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileType.java
index 613ffaa..56b8997 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileType.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/FileType.java
@@ -63,20 +63,19 @@ public enum FileType {
     /**
      * Returns the name of this type.
      *
-     * @return The name of this type.
+     * @return The name of the type.
      */
-    @Override
-    public String toString() {
+    public String getName() {
         return name;
     }
 
     /**
-     * Returns the name of this type.
+     * Returns true if files of this type may have attributes.
      *
-     * @return The name of the type.
+     * @return true if files can have attributes
      */
-    public String getName() {
-        return name;
+    public boolean hasAttributes() {
+        return hasAttrs;
     }
 
     /**
@@ -98,11 +97,12 @@ public enum FileType {
     }
 
     /**
-     * Returns true if files of this type may have attributes.
+     * Returns the name of this type.
      *
-     * @return true if files can have attributes
+     * @return The name of this type.
      */
-    public boolean hasAttributes() {
-        return hasAttrs;
+    @Override
+    public String toString() {
+        return name;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/InvertIncludeFileSelector.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/InvertIncludeFileSelector.java
index 710a53d..30f4acd 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/InvertIncludeFileSelector.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/InvertIncludeFileSelector.java
@@ -25,6 +25,8 @@ import java.util.Objects;
  */
 public class InvertIncludeFileSelector implements FileSelector {
 
+    private final FileSelector delegateFileSelector;
+
     /**
      * Constructs a new instance.
      *
@@ -34,8 +36,6 @@ public class InvertIncludeFileSelector implements FileSelector {
         this.delegateFileSelector = Objects.requireNonNull(delegateFileSelector, "delegateFileSelector");
     }
 
-    private final FileSelector delegateFileSelector;
-
     /**
      * Inverts the result of calling {@link #includeFile(FileSelectInfo)} on the delegate.
      */
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/NameScope.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/NameScope.java
index ed0efeb..190a4d9 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/NameScope.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/NameScope.java
@@ -68,8 +68,7 @@ public enum NameScope {
      *
      * @return The name of the scope.
      */
-    @Override
-    public String toString() {
+    public String getName() {
         return realName;
     }
 
@@ -78,7 +77,8 @@ public enum NameScope {
      *
      * @return The name of the scope.
      */
-    public String getName() {
+    @Override
+    public String toString() {
         return realName;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/UserAuthenticationData.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/UserAuthenticationData.java
index 418a8ed..9bb8c60 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/UserAuthenticationData.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/UserAuthenticationData.java
@@ -44,6 +44,11 @@ public class UserAuthenticationData {
         }
 
         @Override
+        public int compareTo(final Type o) {
+            return type.compareTo(o.type);
+        }
+
+        @Override
         public boolean equals(final Object o) {
             if (this == o) {
                 return true;
@@ -54,11 +59,6 @@ public class UserAuthenticationData {
             return Objects.equals(type, ((Type) o).type);
         }
 
-        @Override
-        public int compareTo(final Type o) {
-            return type.compareTo(o.type);
-        }
-
         /**
          * @return The hash code.
          * @since 2.0
@@ -98,13 +98,19 @@ public class UserAuthenticationData {
     }
 
     /**
-     * Sets a data to this collection.
-     *
-     * @param type The Type to add
-     * @param data The data associated with the Type
+     * Deletes all data stored within this authenticator.
      */
-    public void setData(final Type type, final char[] data) {
-        authenticationData.put(type, data);
+    public void cleanup() {
+        // step 1: nullify character buffers
+        for (final char[] data : authenticationData.values()) {
+            if (data == null) {
+                continue;
+            }
+
+            Arrays.fill(data, (char) 0);
+        }
+        // step 2: allow data itself to gc
+        authenticationData.clear();
     }
 
     /**
@@ -118,18 +124,12 @@ public class UserAuthenticationData {
     }
 
     /**
-     * Deletes all data stored within this authenticator.
+     * Sets a data to this collection.
+     *
+     * @param type The Type to add
+     * @param data The data associated with the Type
      */
-    public void cleanup() {
-        // step 1: nullify character buffers
-        for (final char[] data : authenticationData.values()) {
-            if (data == null) {
-                continue;
-            }
-
-            Arrays.fill(data, (char) 0);
-        }
-        // step 2: allow data itself to gc
-        authenticationData.clear();
+    public void setData(final Type type, final char[] data) {
+        authenticationData.put(type, data);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/VfsLog.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/VfsLog.java
index 7d89f2b..c4a5018 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/VfsLog.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/VfsLog.java
@@ -29,157 +29,157 @@ public final class VfsLog {
     }
 
     /**
-     * warning.
+     * debug.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonslog The class specific Logger
      * @param message The message to log.
-     * @param t The exception, if any.
      */
-    public static void warn(final Log vfsLog, final Log commonslog, final String message, final Throwable t) {
+    public static void debug(final Log vfsLog, final Log commonslog, final String message) {
         if (vfsLog != null) {
-            vfsLog.warn(message, t);
+            vfsLog.debug(message);
         } else if (commonslog != null) {
-            commonslog.warn(message, t);
+            commonslog.debug(message);
         }
     }
 
     /**
-     * warning.
+     * debug.
      *
      * @param vfsLog The base component Logger to use.
-     * @param commonslog The class specific Logger
+     * @param commonsLog The class specific Logger
      * @param message The message to log.
+     * @param t The exception, if any.
      */
-    public static void warn(final Log vfsLog, final Log commonslog, final String message) {
+    public static void debug(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
         if (vfsLog != null) {
-            vfsLog.warn(message);
-        } else if (commonslog != null) {
-            commonslog.warn(message);
+            vfsLog.debug(message, t);
+        } else if (commonsLog != null) {
+            commonsLog.debug(message, t);
         }
     }
 
     /**
-     * debug.
+     * error.
      *
      * @param vfsLog The base component Logger to use.
-     * @param commonslog The class specific Logger
+     * @param commonsLog The class specific Logger
      * @param message The message to log.
      */
-    public static void debug(final Log vfsLog, final Log commonslog, final String message) {
+    public static void error(final Log vfsLog, final Log commonsLog, final String message) {
         if (vfsLog != null) {
-            vfsLog.debug(message);
-        } else if (commonslog != null) {
-            commonslog.debug(message);
+            vfsLog.error(message);
+        } else if (commonsLog != null) {
+            commonsLog.error(message);
         }
     }
 
     /**
-     * debug.
+     * error.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonsLog The class specific Logger
      * @param message The message to log.
      * @param t The exception, if any.
      */
-    public static void debug(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
+    public static void error(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
         if (vfsLog != null) {
-            vfsLog.debug(message, t);
+            vfsLog.error(message, t);
         } else if (commonsLog != null) {
-            commonsLog.debug(message, t);
+            commonsLog.error(message, t);
         }
     }
 
     /**
-     * info.
+     * fatal.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonsLog The class specific Logger
      * @param message The message to log.
-     * @param t The exception, if any.
      */
-    public static void info(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
+    public static void fatal(final Log vfsLog, final Log commonsLog, final String message) {
         if (vfsLog != null) {
-            vfsLog.info(message, t);
+            vfsLog.fatal(message);
         } else if (commonsLog != null) {
-            commonsLog.info(message, t);
+            commonsLog.fatal(message);
         }
     }
 
     /**
-     * info.
+     * fatal.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonsLog The class specific Logger
      * @param message The message to log.
+     * @param t The exception, if any.
      */
-    public static void info(final Log vfsLog, final Log commonsLog, final String message) {
+    public static void fatal(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
         if (vfsLog != null) {
-            vfsLog.info(message);
+            vfsLog.fatal(message, t);
         } else if (commonsLog != null) {
-            commonsLog.info(message);
+            commonsLog.fatal(message, t);
         }
     }
 
     /**
-     * error.
+     * info.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonsLog The class specific Logger
      * @param message The message to log.
-     * @param t The exception, if any.
      */
-    public static void error(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
+    public static void info(final Log vfsLog, final Log commonsLog, final String message) {
         if (vfsLog != null) {
-            vfsLog.error(message, t);
+            vfsLog.info(message);
         } else if (commonsLog != null) {
-            commonsLog.error(message, t);
+            commonsLog.info(message);
         }
     }
 
     /**
-     * error.
+     * info.
      *
      * @param vfsLog The base component Logger to use.
      * @param commonsLog The class specific Logger
      * @param message The message to log.
+     * @param t The exception, if any.
      */
-    public static void error(final Log vfsLog, final Log commonsLog, final String message) {
+    public static void info(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
         if (vfsLog != null) {
-            vfsLog.error(message);
+            vfsLog.info(message, t);
         } else if (commonsLog != null) {
-            commonsLog.error(message);
+            commonsLog.info(message, t);
         }
     }
 
     /**
-     * fatal.
+     * warning.
      *
      * @param vfsLog The base component Logger to use.
-     * @param commonsLog The class specific Logger
+     * @param commonslog The class specific Logger
      * @param message The message to log.
-     * @param t The exception, if any.
      */
-    public static void fatal(final Log vfsLog, final Log commonsLog, final String message, final Throwable t) {
+    public static void warn(final Log vfsLog, final Log commonslog, final String message) {
         if (vfsLog != null) {
-            vfsLog.fatal(message, t);
-        } else if (commonsLog != null) {
-            commonsLog.fatal(message, t);
+            vfsLog.warn(message);
+        } else if (commonslog != null) {
+            commonslog.warn(message);
         }
     }
 
     /**
-     * fatal.
+     * warning.
      *
      * @param vfsLog The base component Logger to use.
-     * @param commonsLog The class specific Logger
+     * @param commonslog The class specific Logger
      * @param message The message to log.
+     * @param t The exception, if any.
      */
-    public static void fatal(final Log vfsLog, final Log commonsLog, final String message) {
+    public static void warn(final Log vfsLog, final Log commonslog, final String message, final Throwable t) {
         if (vfsLog != null) {
-            vfsLog.fatal(message);
-        } else if (commonsLog != null) {
-            commonsLog.fatal(message);
+            vfsLog.warn(message, t);
+        } else if (commonslog != null) {
+            commonslog.warn(message, t);
         }
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/auth/StaticUserAuthenticator.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/auth/StaticUserAuthenticator.java
index ce107c8..e0862d8 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/auth/StaticUserAuthenticator.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/auth/StaticUserAuthenticator.java
@@ -53,23 +53,19 @@ public class StaticUserAuthenticator implements UserAuthenticator, Comparable<St
         this.domain = domain;
     }
 
-    @Override
-    public UserAuthenticationData requestAuthentication(final UserAuthenticationData.Type[] types) {
-        final UserAuthenticationData data = new UserAuthenticationData();
-        for (final UserAuthenticationData.Type type : types) {
-            if (type == UserAuthenticationData.DOMAIN) {
-                data.setData(UserAuthenticationData.DOMAIN, UserAuthenticatorUtils.toChar(domain));
-            } else if (type == UserAuthenticationData.USERNAME) {
-                data.setData(UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(username));
-            } else if (type == UserAuthenticationData.PASSWORD) {
-                data.setData(UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(password));
-            } else if (LOG.isDebugEnabled()) {
-                LOG.debug(StaticUserAuthenticator.class.getSimpleName()
-                        + " does not support authentication data type '" + type
-                        + "'; authentication request for this type ignored.");
+    private int compareStringOrNull(final String thisString, final String otherString) {
+        if (thisString != null) {
+            if (otherString == null) {
+                return 1;
             }
+
+            return thisString.compareTo(otherString);
         }
-        return data;
+        if (otherString != null) {
+            return -1;
+        }
+
+        return 0;
     }
 
     /**
@@ -78,12 +74,10 @@ public class StaticUserAuthenticator implements UserAuthenticator, Comparable<St
      * @since 2.0
      */
     @Override
-    public int hashCode() {
-        final int prime = 37;
-        int result = 1;
-        result = prime * result + (domain == null ? 0 : domain.hashCode());
-        result = prime * result + (password == null ? 0 : password.hashCode());
-        result = prime * result + (username == null ? 0 : username.hashCode());
+    public int compareTo(final StaticUserAuthenticator other) {
+        int result = compareStringOrNull(domain, other.domain);
+        result = result == 0 ? compareStringOrNull(username, other.username) : result;
+        result = result == 0 ? compareStringOrNull(password, other.password) : result;
 
         return result;
     }
@@ -118,27 +112,33 @@ public class StaticUserAuthenticator implements UserAuthenticator, Comparable<St
      * @since 2.0
      */
     @Override
-    public int compareTo(final StaticUserAuthenticator other) {
-        int result = compareStringOrNull(domain, other.domain);
-        result = result == 0 ? compareStringOrNull(username, other.username) : result;
-        result = result == 0 ? compareStringOrNull(password, other.password) : result;
+    public int hashCode() {
+        final int prime = 37;
+        int result = 1;
+        result = prime * result + (domain == null ? 0 : domain.hashCode());
+        result = prime * result + (password == null ? 0 : password.hashCode());
+        result = prime * result + (username == null ? 0 : username.hashCode());
 
         return result;
     }
 
-    private int compareStringOrNull(final String thisString, final String otherString) {
-        if (thisString != null) {
-            if (otherString == null) {
-                return 1;
+    @Override
+    public UserAuthenticationData requestAuthentication(final UserAuthenticationData.Type[] types) {
+        final UserAuthenticationData data = new UserAuthenticationData();
+        for (final UserAuthenticationData.Type type : types) {
+            if (type == UserAuthenticationData.DOMAIN) {
+                data.setData(UserAuthenticationData.DOMAIN, UserAuthenticatorUtils.toChar(domain));
+            } else if (type == UserAuthenticationData.USERNAME) {
+                data.setData(UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(username));
+            } else if (type == UserAuthenticationData.PASSWORD) {
+                data.setData(UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(password));
+            } else if (LOG.isDebugEnabled()) {
+                LOG.debug(StaticUserAuthenticator.class.getSimpleName()
+                        + " does not support authentication data type '" + type
+                        + "'; authentication request for this type ignored.");
             }
-
-            return thisString.compareTo(otherString);
         }
-        if (otherString != null) {
-            return -1;
-        }
-
-        return 0;
+        return data;
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/DefaultFilesCache.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/DefaultFilesCache.java
index 70439b2..4284b71 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/DefaultFilesCache.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/DefaultFilesCache.java
@@ -51,15 +51,18 @@ public class DefaultFilesCache extends AbstractFilesCache {
     private final ConcurrentMap<FileSystem, ConcurrentMap<FileName, FileObject>> fileSystemCache = new ConcurrentHashMap<>(10);
 
     @Override
-    public void putFile(final FileObject file) {
-        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
-        files.put(file.getName(), file);
+    public void clear(final FileSystem filesystem) {
+        // avoid keeping a reference to the FileSystem (key) object
+        final Map<FileName, FileObject> files = fileSystemCache.remove(filesystem);
+        if (files != null) {
+            files.clear(); // help GC
+        }
     }
 
     @Override
-    public boolean putFileIfAbsent(final FileObject file) {
-        final ConcurrentMap<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
-        return files.putIfAbsent(file.getName(), file) == null;
+    public void close() {
+        super.close();
+        fileSystemCache.clear();
     }
 
     @Override
@@ -74,15 +77,6 @@ public class DefaultFilesCache extends AbstractFilesCache {
         return files.get(name); // or null
     }
 
-    @Override
-    public void clear(final FileSystem filesystem) {
-        // avoid keeping a reference to the FileSystem (key) object
-        final Map<FileName, FileObject> files = fileSystemCache.remove(filesystem);
-        if (files != null) {
-            files.clear(); // help GC
-        }
-    }
-
     protected ConcurrentMap<FileName, FileObject> getOrCreateFilesystemCache(final FileSystem filesystem) {
         ConcurrentMap<FileName, FileObject> files = fileSystemCache.get(filesystem);
         // we loop to make sure we never return null even when concurrent clean is called
@@ -95,9 +89,15 @@ public class DefaultFilesCache extends AbstractFilesCache {
     }
 
     @Override
-    public void close() {
-        super.close();
-        fileSystemCache.clear();
+    public void putFile(final FileObject file) {
+        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
+        files.put(file.getName(), file);
+    }
+
+    @Override
+    public boolean putFileIfAbsent(final FileObject file) {
+        final ConcurrentMap<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
+        return files.putIfAbsent(file.getName(), file) == null;
     }
 
     @Override
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/FileSystemAndNameKey.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/FileSystemAndNameKey.java
index 55d9dee..9cec28a 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/FileSystemAndNameKey.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/FileSystemAndNameKey.java
@@ -54,11 +54,11 @@ final class FileSystemAndNameKey implements Comparable<FileSystemAndNameKey> {
         return fileName.compareTo(other.fileName);
     }
 
-    FileSystem getFileSystem() {
-        return fileSystem;
-    }
-
     FileName getFileName() {
         return fileName;
     }
+
+    FileSystem getFileSystem() {
+        return fileSystem;
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/LRUFilesCache.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/LRUFilesCache.java
index f0aaa6c..aacf64f 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/LRUFilesCache.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/LRUFilesCache.java
@@ -42,22 +42,6 @@ import org.apache.commons.vfs2.util.Messages;
  */
 public class LRUFilesCache extends AbstractFilesCache {
 
-    /** The default LRU size */
-    private static final int DEFAULT_LRU_SIZE = 100;
-
-    /** The logger to use. */
-    private static final Log log = LogFactory.getLog(LRUFilesCache.class);
-
-    /** The FileSystem cache */
-    private final ConcurrentMap<FileSystem, Map<FileName, FileObject>> fileSystemCache = new ConcurrentHashMap<>();
-
-    /** The size of the cache */
-    private final int lruSize;
-
-    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
-    private final Lock readLock = rwLock.readLock();
-    private final Lock writeLock = rwLock.writeLock();
-
     /**
      * The file cache
      */
@@ -113,6 +97,22 @@ public class LRUFilesCache extends AbstractFilesCache {
         }
     }
 
+    /** The default LRU size */
+    private static final int DEFAULT_LRU_SIZE = 100;
+
+    /** The logger to use. */
+    private static final Log log = LogFactory.getLog(LRUFilesCache.class);
+
+    /** The FileSystem cache */
+    private final ConcurrentMap<FileSystem, Map<FileName, FileObject>> fileSystemCache = new ConcurrentHashMap<>();
+
+    /** The size of the cache */
+    private final int lruSize;
+    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
+    private final Lock readLock = rwLock.readLock();
+
+    private final Lock writeLock = rwLock.writeLock();
+
     /**
      * Default constructor. Uses a LRU size of 100 per file system.
      */
@@ -130,34 +130,23 @@ public class LRUFilesCache extends AbstractFilesCache {
     }
 
     @Override
-    public void putFile(final FileObject file) {
-        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
+    public void clear(final FileSystem filesystem) {
+        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(filesystem);
 
         writeLock.lock();
         try {
-            files.put(file.getName(), file);
+            files.clear();
+
+            fileSystemCache.remove(filesystem);
         } finally {
             writeLock.unlock();
         }
     }
 
     @Override
-    public boolean putFileIfAbsent(final FileObject file) {
-        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
-
-        writeLock.lock();
-        try {
-            final FileName name = file.getName();
-
-            if (files.containsKey(name)) {
-                return false;
-            }
-
-            files.put(name, file);
-            return true;
-        } finally {
-            writeLock.unlock();
-        }
+    public void close() {
+        super.close();
+        fileSystemCache.clear();
     }
 
     @Override
@@ -172,28 +161,39 @@ public class LRUFilesCache extends AbstractFilesCache {
         }
     }
 
+    protected Map<FileName, FileObject> getOrCreateFilesystemCache(final FileSystem fileSystem) {
+        return fileSystemCache.computeIfAbsent(fileSystem, k -> new MyLRUMap(k, lruSize));
+    }
+
     @Override
-    public void clear(final FileSystem filesystem) {
-        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(filesystem);
+    public void putFile(final FileObject file) {
+        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
 
         writeLock.lock();
         try {
-            files.clear();
-
-            fileSystemCache.remove(filesystem);
+            files.put(file.getName(), file);
         } finally {
             writeLock.unlock();
         }
     }
 
-    protected Map<FileName, FileObject> getOrCreateFilesystemCache(final FileSystem fileSystem) {
-        return fileSystemCache.computeIfAbsent(fileSystem, k -> new MyLRUMap(k, lruSize));
-    }
-
     @Override
-    public void close() {
-        super.close();
-        fileSystemCache.clear();
+    public boolean putFileIfAbsent(final FileObject file) {
+        final Map<FileName, FileObject> files = getOrCreateFilesystemCache(file.getFileSystem());
+
+        writeLock.lock();
+        try {
+            final FileName name = file.getName();
+
+            if (files.containsKey(name)) {
+                return false;
+            }
+
+            files.put(name, file);
+            return true;
+        } finally {
+            writeLock.unlock();
+        }
     }
 
     @Override
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/NullFilesCache.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/NullFilesCache.java
index 880c494..cca6b51 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/NullFilesCache.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/NullFilesCache.java
@@ -33,26 +33,26 @@ import org.apache.commons.vfs2.FileSystem;
 public class NullFilesCache extends AbstractFilesCache {
 
     @Override
-    public void putFile(final FileObject file) {
+    public void clear(final FileSystem filesystem) {
         // empty
     }
 
     @Override
-    public boolean putFileIfAbsent(final FileObject file) {
-        return false;
-    }
-
-    @Override
     public FileObject getFile(final FileSystem filesystem, final FileName name) {
         return null;
     }
 
     @Override
-    public void clear(final FileSystem filesystem) {
+    public void putFile(final FileObject file) {
         // empty
     }
 
     @Override
+    public boolean putFileIfAbsent(final FileObject file) {
+        return false;
+    }
+
+    @Override
     public void removeFile(final FileSystem filesystem, final FileName name) {
         // empty
     }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java
index 14620d2..975574f 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/cache/OnCallRefreshFileObject.java
@@ -83,16 +83,16 @@ public class OnCallRefreshFileObject extends DecoratedFileObject {
     }
 
     @Override
-    public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
-            throws FileSystemException {
+    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
         refresh();
-        super.findFiles(selector, depthwise, selected);
+        return super.findFiles(selector);
     }
 
     @Override
-    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
+    public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
+            throws FileSystemException {
         refresh();
-        return super.findFiles(selector);
+        super.findFiles(selector, depthwise, selected);
     }
 
     @Override
@@ -144,38 +144,38 @@ public class OnCallRefreshFileObject extends DecoratedFileObject {
     }
 
     @Override
-    public boolean setExecutable(final boolean executable, final boolean ownerOnly) throws FileSystemException {
+    public void moveTo(final FileObject destFile) throws FileSystemException {
         refresh();
-        return super.setExecutable(executable, ownerOnly);
+        super.moveTo(destFile);
     }
 
     @Override
-    public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
+    public FileObject resolveFile(final String path) throws FileSystemException {
         refresh();
-        return super.setReadable(readable, ownerOnly);
+        return super.resolveFile(path);
     }
 
     @Override
-    public boolean setWritable(final boolean writable, final boolean ownerOnly) throws FileSystemException {
+    public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
         refresh();
-        return super.setWritable(writable, ownerOnly);
+        return super.resolveFile(name, scope);
     }
 
     @Override
-    public void moveTo(final FileObject destFile) throws FileSystemException {
+    public boolean setExecutable(final boolean executable, final boolean ownerOnly) throws FileSystemException {
         refresh();
-        super.moveTo(destFile);
+        return super.setExecutable(executable, ownerOnly);
     }
 
     @Override
-    public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
+    public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
         refresh();
-        return super.resolveFile(name, scope);
+        return super.setReadable(readable, ownerOnly);
     }
 
     @Override
-    public FileObject resolveFile(final String path) throws FileSystemException {
+    public boolean setWritable(final boolean writable, final boolean ownerOnly) throws FileSystemException {
         refresh();
-        return super.resolveFile(path);
+        return super.setWritable(writable, ownerOnly);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/NameFileFilter.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/NameFileFilter.java
index 0684ee2..e50d9fe 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/NameFileFilter.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/NameFileFilter.java
@@ -55,15 +55,6 @@ public class NameFileFilter implements FileFilter, Serializable {
     private final List<String> names;
 
     /**
-     * Constructs a new case-sensitive name file filter for a list of names.
-     *
-     * @param names the names to allow, must not be null
-     */
-    public NameFileFilter(final List<String> names) {
-        this((IOCase) null, names);
-    }
-
-    /**
      * Constructs a new name file filter for a list of names specifying
      * case-sensitivity.
      *
@@ -80,19 +71,6 @@ public class NameFileFilter implements FileFilter, Serializable {
     }
 
     /**
-     * Constructs a new case-sensitive name file filter for an array of names.
-     * <p>
-     * The array is not cloned, so could be changed after constructing the instance.
-     * This would be inadvisable however.
-     * </p>
-     *
-     * @param names the names to allow, must not be null
-     */
-    public NameFileFilter(final String... names) {
-        this((IOCase) null, names);
-    }
-
-    /**
      * Constructs a new name file filter for an array of names specifying
      * case-sensitivity.
      *
@@ -109,6 +87,28 @@ public class NameFileFilter implements FileFilter, Serializable {
     }
 
     /**
+     * Constructs a new case-sensitive name file filter for a list of names.
+     *
+     * @param names the names to allow, must not be null
+     */
+    public NameFileFilter(final List<String> names) {
+        this((IOCase) null, names);
+    }
+
+    /**
+     * Constructs a new case-sensitive name file filter for an array of names.
+     * <p>
+     * The array is not cloned, so could be changed after constructing the instance.
+     * This would be inadvisable however.
+     * </p>
+     *
+     * @param names the names to allow, must not be null
+     */
+    public NameFileFilter(final String... names) {
+        this((IOCase) null, names);
+    }
+
+    /**
      * Checks to see if the file name matches.
      *
      * @param fileSelectInfo the File to check
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/PrefixFileFilter.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/PrefixFileFilter.java
index 7ebc28e..4c17d0b 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/PrefixFileFilter.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/PrefixFileFilter.java
@@ -55,15 +55,6 @@ public class PrefixFileFilter implements FileFilter, Serializable {
     private final List<String> prefixes;
 
     /**
-     * Constructs a new Prefix file filter for a list of prefixes.
-     *
-     * @param prefixes the prefixes to allow, must not be null
-     */
-    public PrefixFileFilter(final List<String> prefixes) {
-        this(IOCase.SENSITIVE, prefixes);
-    }
-
-    /**
      * Constructs a new Prefix file filter for a list of prefixes specifying
      * case-sensitivity.
      *
@@ -80,18 +71,6 @@ public class PrefixFileFilter implements FileFilter, Serializable {
     }
 
     /**
-     * Constructs a new Prefix file filter for any of an array of prefixes.
-     * <p>
-     * The array is not cloned, so could be changed after constructing the instance.
-     * This would be inadvisable however.
-     *
-     * @param prefixes the prefixes to allow, must not be null
-     */
-    public PrefixFileFilter(final String... prefixes) {
-        this(IOCase.SENSITIVE, prefixes);
-    }
-
-    /**
      * Constructs a new Prefix file filter for any of an array of prefixes
      * specifying case-sensitivity.
      *
@@ -108,6 +87,27 @@ public class PrefixFileFilter implements FileFilter, Serializable {
     }
 
     /**
+     * Constructs a new Prefix file filter for a list of prefixes.
+     *
+     * @param prefixes the prefixes to allow, must not be null
+     */
+    public PrefixFileFilter(final List<String> prefixes) {
+        this(IOCase.SENSITIVE, prefixes);
+    }
+
+    /**
+     * Constructs a new Prefix file filter for any of an array of prefixes.
+     * <p>
+     * The array is not cloned, so could be changed after constructing the instance.
+     * This would be inadvisable however.
+     *
+     * @param prefixes the prefixes to allow, must not be null
+     */
+    public PrefixFileFilter(final String... prefixes) {
+        this(IOCase.SENSITIVE, prefixes);
+    }
+
+    /**
      * Checks to see if the file name starts with the prefix.
      *
      * @param fileSelectInfo the File to check
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/SuffixFileFilter.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/SuffixFileFilter.java
index 68e609f..a1095c4 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/SuffixFileFilter.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/SuffixFileFilter.java
@@ -56,15 +56,6 @@ public class SuffixFileFilter implements FileFilter, Serializable {
     private final List<String> suffixes;
 
     /**
-     * Constructs a new Suffix file filter for a list of suffixes.
-     *
-     * @param suffixes the suffixes to allow, must not be null
-     */
-    public SuffixFileFilter(final List<String> suffixes) {
-        this(IOCase.SENSITIVE, suffixes);
-    }
-
-    /**
      * Constructs a new Suffix file filter for a list of suffixes specifying
      * case-sensitivity.
      *
@@ -81,15 +72,6 @@ public class SuffixFileFilter implements FileFilter, Serializable {
     }
 
     /**
-     * Constructs a new Suffix file filter for an array of suffixes.
-     *
-     * @param suffixes the suffixes to allow, must not be null
-     */
-    public SuffixFileFilter(final String... suffixes) {
-        this(IOCase.SENSITIVE, suffixes);
-    }
-
-    /**
      * Constructs a new Suffix file filter for an array of suffixs specifying
      * case-sensitivity.
      *
@@ -106,6 +88,24 @@ public class SuffixFileFilter implements FileFilter, Serializable {
     }
 
     /**
+     * Constructs a new Suffix file filter for a list of suffixes.
+     *
+     * @param suffixes the suffixes to allow, must not be null
+     */
+    public SuffixFileFilter(final List<String> suffixes) {
+        this(IOCase.SENSITIVE, suffixes);
+    }
+
+    /**
+     * Constructs a new Suffix file filter for an array of suffixes.
+     *
+     * @param suffixes the suffixes to allow, must not be null
+     */
+    public SuffixFileFilter(final String... suffixes) {
+        this(IOCase.SENSITIVE, suffixes);
+    }
+
+    /**
      * Checks to see if the file name ends with the suffix.
      *
      * @param fileSelectInfo the File to check
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/WildcardFileFilter.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/WildcardFileFilter.java
index 7d85df4..515ca13 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/WildcardFileFilter.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/filter/WildcardFileFilter.java
@@ -68,15 +68,6 @@ public class WildcardFileFilter implements FileFilter, Serializable {
     private final List<String> wildcards;
 
     /**
-     * Construct a new case-sensitive wildcard filter for a list of wildcards.
-     *
-     * @param wildcards the list of wildcards to match, not null
-     */
-    public WildcardFileFilter(final List<String> wildcards) {
-        this((IOCase) null, wildcards);
-    }
-
-    /**
      * Construct a new wildcard filter for a list of wildcards specifying
      * case-sensitivity.
      *
@@ -93,18 +84,6 @@ public class WildcardFileFilter implements FileFilter, Serializable {
     }
 
     /**
-     * Construct a new case-sensitive wildcard filter for an array of wildcards.
-     * <p>
-     * The array is not cloned, so could be changed after constructing the instance.
-     * This would be inadvisable however.
-     *
-     * @param wildcards the array of wildcards to match
-     */
-    public WildcardFileFilter(final String... wildcards) {
-        this((IOCase) null, wildcards);
-    }
-
-    /**
      * Construct a new wildcard filter for an array of wildcards specifying
      * case-sensitivity.
      *
@@ -121,43 +100,24 @@ public class WildcardFileFilter implements FileFilter, Serializable {
     }
 
     /**
-     * Checks to see if the file name matches one of the wildcards.
-     *
-     * @param fileSelectInfo the file to check
+     * Construct a new case-sensitive wildcard filter for a list of wildcards.
      *
-     * @return true if the file name matches one of the wildcards
+     * @param wildcards the list of wildcards to match, not null
      */
-    @Override
-    public boolean accept(final FileSelectInfo fileSelectInfo) {
-        final String name = fileSelectInfo.getFile().getName().getBaseName();
-        for (final String wildcard : wildcards) {
-            if (wildcardMatch(name, wildcard, caseSensitivity)) {
-                return true;
-            }
-        }
-        return false;
+    public WildcardFileFilter(final List<String> wildcards) {
+        this((IOCase) null, wildcards);
     }
 
     /**
-     * Provide a String representation of this file filter.
+     * Construct a new case-sensitive wildcard filter for an array of wildcards.
+     * <p>
+     * The array is not cloned, so could be changed after constructing the instance.
+     * This would be inadvisable however.
      *
-     * @return a String representation
+     * @param wildcards the array of wildcards to match
      */
-    @Override
-    public String toString() {
-        final StringBuilder buffer = new StringBuilder();
-        buffer.append(super.toString());
-        buffer.append("(");
-        if (wildcards != null) {
-            for (int i = 0; i < wildcards.size(); i++) {
-                if (i > 0) {
-                    buffer.append(",");
-                }
-                buffer.append(wildcards.get(i));
-            }
-        }
-        buffer.append(")");
-        return buffer.toString();
+    public WildcardFileFilter(final String... wildcards) {
+        this((IOCase) null, wildcards);
     }
 
     /**
@@ -201,8 +161,6 @@ public class WildcardFileFilter implements FileFilter, Serializable {
         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
     }
 
-    // CHECKSTYLE:ON
-
     /**
      * Checks a file name to see if it matches the specified wildcard matcher
      * allowing control over case-sensitivity.
@@ -302,4 +260,46 @@ public class WildcardFileFilter implements FileFilter, Serializable {
     }
     // CHECKSTYLE:ON
 
+    /**
+     * Checks to see if the file name matches one of the wildcards.
+     *
+     * @param fileSelectInfo the file to check
+     *
+     * @return true if the file name matches one of the wildcards
+     */
+    @Override
+    public boolean accept(final FileSelectInfo fileSelectInfo) {
+        final String name = fileSelectInfo.getFile().getName().getBaseName();
+        for (final String wildcard : wildcards) {
+            if (wildcardMatch(name, wildcard, caseSensitivity)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // CHECKSTYLE:ON
+
+    /**
+     * Provide a String representation of this file filter.
+     *
+     * @return a String representation
+     */
+    @Override
+    public String toString() {
+        final StringBuilder buffer = new StringBuilder();
+        buffer.append(super.toString());
+        buffer.append("(");
+        if (wildcards != null) {
+            for (int i = 0; i < wildcards.size(); i++) {
+                if (i > 0) {
+                    buffer.append(",");
+                }
+                buffer.append(wildcards.get(i));
+            }
+        }
+        buffer.append(")");
+        return buffer.toString();
+    }
+
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java
index 3969e2d..a1db722 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DecoratedFileObject.java
@@ -142,11 +142,6 @@ public class DecoratedFileObject implements FileObject {
     }
 
     @Override
-    public String getPublicURIString() {
-        return fileObject.getPublicURIString();
-    }
-
-    @Override
     public FileName getName() {
         return fileObject.getName();
     }
@@ -157,6 +152,11 @@ public class DecoratedFileObject implements FileObject {
     }
 
     @Override
+    public String getPublicURIString() {
+        return fileObject.getPublicURIString();
+    }
+
+    @Override
     public FileType getType() throws FileSystemException {
         return fileObject.getType();
     }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileContentInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileContentInfo.java
index 349ed3d..fe28ec0 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileContentInfo.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileContentInfo.java
@@ -38,12 +38,12 @@ public class DefaultFileContentInfo implements FileContentInfo {
     }
 
     @Override
-    public String getContentType() {
-        return contentType;
+    public String getContentEncoding() {
+        return contentEncoding;
     }
 
     @Override
-    public String getContentEncoding() {
-        return contentEncoding;
+    public String getContentType() {
+        return contentType;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemConfigBuilder.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemConfigBuilder.java
index 98ae6db..edc9051 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemConfigBuilder.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultFileSystemConfigBuilder.java
@@ -25,6 +25,12 @@ import org.apache.commons.vfs2.UserAuthenticator;
  * Default options usable for all file systems.
  */
 public class DefaultFileSystemConfigBuilder extends FileSystemConfigBuilder {
+    /**
+     * Dummy class that implements FileSystem.
+     */
+    abstract static class DefaultFileSystem implements FileSystem {
+    }
+
     /** The default FileSystemConfigBuilder */
     private static final DefaultFileSystemConfigBuilder BUILDER = new DefaultFileSystemConfigBuilder();
 
@@ -37,14 +43,9 @@ public class DefaultFileSystemConfigBuilder extends FileSystemConfigBuilder {
         return BUILDER;
     }
 
-    /**
-     * Sets the user authenticator to get authentication informations.
-     *
-     * @param opts The FileSystemOptions.
-     * @param userAuthenticator The UserAuthenticator.
-     */
-    public void setUserAuthenticator(final FileSystemOptions opts, final UserAuthenticator userAuthenticator) {
-        setParam(opts, "userAuthenticator", userAuthenticator);
+    @Override
+    protected Class<? extends FileSystem> getConfigClass() {
+        return DefaultFileSystem.class;
     }
 
     /**
@@ -57,13 +58,12 @@ public class DefaultFileSystemConfigBuilder extends FileSystemConfigBuilder {
     }
 
     /**
-     * Dummy class that implements FileSystem.
+     * Sets the user authenticator to get authentication informations.
+     *
+     * @param opts The FileSystemOptions.
+     * @param userAuthenticator The UserAuthenticator.
      */
-    abstract static class DefaultFileSystem implements FileSystem {
-    }
-
-    @Override
-    protected Class<? extends FileSystem> getConfigClass() {
-        return DefaultFileSystem.class;
+    public void setUserAuthenticator(final FileSystemOptions opts, final UserAuthenticator userAuthenticator) {
+        setParam(opts, "userAuthenticator", userAuthenticator);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultVfsComponentContext.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultVfsComponentContext.java
index 9b3534e..f8d1d03 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultVfsComponentContext.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/DefaultVfsComponentContext.java
@@ -38,59 +38,59 @@ final class DefaultVfsComponentContext implements VfsComponentContext {
     }
 
     /**
-     * Locate a file by name.
+     * Returns the file system manager for the current context
+     *
+     * @return the file system manager
      */
     @Override
-    public FileObject resolveFile(final FileObject baseFile, final String name,
-            final FileSystemOptions fileSystemOptions) throws FileSystemException {
-        return manager.resolveFile(baseFile, name, fileSystemOptions);
+    public FileSystemManager getFileSystemManager() {
+        return manager;
     }
 
     /**
-     * Locate a file by name.
+     * Locates a file replicator for the provider to use.
      */
     @Override
-    public FileObject resolveFile(final String name, final FileSystemOptions fileSystemOptions)
-            throws FileSystemException {
-        return manager.resolveFile(name, fileSystemOptions);
+    public FileReplicator getReplicator() throws FileSystemException {
+        return manager.getReplicator();
     }
 
+    /**
+     * Locates a temporary file store for the provider to use.
+     */
     @Override
-    public FileName parseURI(final String uri) throws FileSystemException {
-        return manager.resolveURI(uri);
+    public TemporaryFileStore getTemporaryFileStore() throws FileSystemException {
+        return manager.getTemporaryFileStore();
     }
 
-    /**
-     * Returns a {@link FileObject} for a local file.
-     */
     @Override
-    public FileObject toFileObject(final File file) throws FileSystemException {
-        return manager.toFileObject(file);
+    public FileName parseURI(final String uri) throws FileSystemException {
+        return manager.resolveURI(uri);
     }
 
     /**
-     * Locates a file replicator for the provider to use.
+     * Locate a file by name.
      */
     @Override
-    public FileReplicator getReplicator() throws FileSystemException {
-        return manager.getReplicator();
+    public FileObject resolveFile(final FileObject baseFile, final String name,
+            final FileSystemOptions fileSystemOptions) throws FileSystemException {
+        return manager.resolveFile(baseFile, name, fileSystemOptions);
     }
 
     /**
-     * Locates a temporary file store for the provider to use.
+     * Locate a file by name.
      */
     @Override
-    public TemporaryFileStore getTemporaryFileStore() throws FileSystemException {
-        return manager.getTemporaryFileStore();
+    public FileObject resolveFile(final String name, final FileSystemOptions fileSystemOptions)
+            throws FileSystemException {
+        return manager.resolveFile(name, fileSystemOptions);
     }
 
     /**
-     * Returns the file system manager for the current context
-     *
-     * @return the file system manager
+     * Returns a {@link FileObject} for a local file.
      */
     @Override
-    public FileSystemManager getFileSystemManager() {
-        return manager;
+    public FileObject toFileObject(final File file) throws FileSystemException {
+        return manager.toFileObject(file);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/PrivilegedFileReplicator.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/PrivilegedFileReplicator.java
index dc6af8e..fcfe5e0 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/PrivilegedFileReplicator.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/PrivilegedFileReplicator.java
@@ -35,7 +35,60 @@ import org.apache.commons.vfs2.provider.VfsComponentContext;
  */
 public class PrivilegedFileReplicator implements FileReplicator, VfsComponent {
 
+    /**
+     * An action that closes the wrapped replicator.
+     */
+    private class CloseAction implements PrivilegedAction<Object> {
+        /**
+         * Performs the action.
+         */
+        @Override
+        public Object run() {
+            replicatorComponent.close();
+            return null;
+        }
+    }
+    /**
+     * An action that initializes the wrapped replicator.
+     */
+    private class InitAction implements PrivilegedExceptionAction<Object> {
+        /**
+         * Performs the action.
+         */
+        @Override
+        public Object run() throws Exception {
+            replicatorComponent.init();
+            return null;
+        }
+    }
+
+    /**
+     * An action that replicates a file using the wrapped replicator.
+     */
+    private class ReplicateAction implements PrivilegedExceptionAction<File> {
+        private final FileObject srcFile;
+        private final FileSelector selector;
+
+        ReplicateAction(final FileObject srcFile, final FileSelector selector) {
+            this.srcFile = srcFile;
+            this.selector = selector;
+        }
+
+        /**
+         * Performs the action.
+         *
+         * @throws Exception if an error occurs.
+         */
+        @Override
+        public File run() throws Exception {
+            // TODO - Do not pass the selector through. It is untrusted
+            // TODO - Need to determine which files can be read
+            return replicator.replicateFile(srcFile, selector);
+        }
+    }
+
     private final FileReplicator replicator;
+
     private final VfsComponent replicatorComponent;
 
     /**
@@ -53,26 +106,12 @@ public class PrivilegedFileReplicator implements FileReplicator, VfsComponent {
     }
 
     /**
-     * Sets the Logger to use for the component.
-     *
-     * @param logger The logger.
-     */
-    @Override
-    public void setLogger(final Log logger) {
-        if (replicatorComponent != null) {
-            replicatorComponent.setLogger(logger);
-        }
-    }
-
-    /**
-     * Sets the context for the replicator.
-     *
-     * @param context The component context.
+     * Closes the replicator.
      */
     @Override
-    public void setContext(final VfsComponentContext context) {
+    public void close() {
         if (replicatorComponent != null) {
-            replicatorComponent.setContext(context);
+            AccessController.doPrivileged(new CloseAction());
         }
     }
 
@@ -93,16 +132,6 @@ public class PrivilegedFileReplicator implements FileReplicator, VfsComponent {
     }
 
     /**
-     * Closes the replicator.
-     */
-    @Override
-    public void close() {
-        if (replicatorComponent != null) {
-            AccessController.doPrivileged(new CloseAction());
-        }
-    }
-
-    /**
      * Creates a local copy of the file, and all its descendants.
      *
      * @param srcFile The source FileObject.
@@ -121,55 +150,26 @@ public class PrivilegedFileReplicator implements FileReplicator, VfsComponent {
     }
 
     /**
-     * An action that initializes the wrapped replicator.
-     */
-    private class InitAction implements PrivilegedExceptionAction<Object> {
-        /**
-         * Performs the action.
-         */
-        @Override
-        public Object run() throws Exception {
-            replicatorComponent.init();
-            return null;
-        }
-    }
-
-    /**
-     * An action that replicates a file using the wrapped replicator.
+     * Sets the context for the replicator.
+     *
+     * @param context The component context.
      */
-    private class ReplicateAction implements PrivilegedExceptionAction<File> {
-        private final FileObject srcFile;
-        private final FileSelector selector;
-
-        ReplicateAction(final FileObject srcFile, final FileSelector selector) {
-            this.srcFile = srcFile;
-            this.selector = selector;
-        }
-
-        /**
-         * Performs the action.
-         *
-         * @throws Exception if an error occurs.
-         */
-        @Override
-        public File run() throws Exception {
-            // TODO - Do not pass the selector through. It is untrusted
-            // TODO - Need to determine which files can be read
-            return replicator.replicateFile(srcFile, selector);
+    @Override
+    public void setContext(final VfsComponentContext context) {
+        if (replicatorComponent != null) {
+            replicatorComponent.setContext(context);
         }
     }
 
     /**
-     * An action that closes the wrapped replicator.
+     * Sets the Logger to use for the component.
+     *
+     * @param logger The logger.
      */
-    private class CloseAction implements PrivilegedAction<Object> {
-        /**
-         * Performs the action.
-         */
-        @Override
-        public Object run() {
-            replicatorComponent.close();
-            return null;
+    @Override
+    public void setLogger(final Log logger) {
+        if (replicatorComponent != null) {
+            replicatorComponent.setLogger(logger);
         }
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/ProviderConfiguration.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/ProviderConfiguration.java
index 4b89c38..b772af3 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/ProviderConfiguration.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/ProviderConfiguration.java
@@ -47,56 +47,56 @@ public class ProviderConfiguration {
     }
 
     /**
-     * sets the class name.
+     * Gets the dependency.
      *
-     * @param className the class name.
+     * @return the dependency.
      */
-    public void setClassName(final String className) {
-        this.className = className;
+    public List<String> getDependencies() {
+        return dependenies;
     }
 
     /**
-     * Sets the scheme.
+     * Gets the schema.
      *
-     * @param scheme the scheme.
+     * @return the scheme.
      */
-    public void setScheme(final String scheme) {
-        schemes.add(scheme);
+    public List<String> getSchemes() {
+        return schemes;
     }
 
     /**
-     * Gets the schema.
+     * Always returns false.
      *
-     * @return the scheme.
+     * @return false.
      */
-    public List<String> getSchemes() {
-        return schemes;
+    public boolean isDefault() {
+        return false;
     }
 
     /**
-     * Sets the dependency.
+     * sets the class name.
      *
-     * @param dependency the dependency.
+     * @param className the class name.
      */
-    public void setDependency(final String dependency) {
-        dependenies.add(dependency);
+    public void setClassName(final String className) {
+        this.className = className;
     }
 
     /**
-     * Gets the dependency.
+     * Sets the dependency.
      *
-     * @return the dependency.
+     * @param dependency the dependency.
      */
-    public List<String> getDependencies() {
-        return dependenies;
+    public void setDependency(final String dependency) {
+        dependenies.add(dependency);
     }
 
     /**
-     * Always returns false.
+     * Sets the scheme.
      *
-     * @return false.
+     * @param scheme the scheme.
      */
-    public boolean isDefault() {
-        return false;
+    public void setScheme(final String scheme) {
+        schemes.add(scheme);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/Resource.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/Resource.java
index f5248d7..cadb33c 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/Resource.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/Resource.java
@@ -55,17 +55,24 @@ final class Resource {
     }
 
     /**
-     * Returns the URL of the resource.
+     * Returns the data for this resource as a byte array.
      */
-    public URL getURL() throws FileSystemException {
-        return resource.getURL();
+    public byte[] getBytes() throws IOException {
+        return FileObjectUtils.getContentAsByteArray(resource);
     }
 
     /**
-     * Returns the name of the package containing the resource.
+     * Returns the code source as an URL.
      */
-    public String getPackageName() {
-        return packageName;
+    public URL getCodeSourceURL() throws FileSystemException {
+        return root.getURL();
+    }
+
+    /**
+     * Returns the FileObject of the resource.
+     */
+    public FileObject getFileObject() {
+        return resource;
     }
 
     /**
@@ -83,23 +90,16 @@ final class Resource {
     }
 
     /**
-     * Returns the FileObject of the resource.
-     */
-    public FileObject getFileObject() {
-        return resource;
-    }
-
-    /**
-     * Returns the code source as an URL.
+     * Returns the name of the package containing the resource.
      */
-    public URL getCodeSourceURL() throws FileSystemException {
-        return root.getURL();
+    public String getPackageName() {
+        return packageName;
     }
 
     /**
-     * Returns the data for this resource as a byte array.
+     * Returns the URL of the resource.
      */
-    public byte[] getBytes() throws IOException {
-        return FileObjectUtils.getContentAsByteArray(resource);
+    public URL getURL() throws FileSystemException {
+        return resource.getURL();
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/StandardFileSystemManager.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/StandardFileSystemManager.java
index 1daf06b..e62eac9 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/StandardFileSystemManager.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/StandardFileSystemManager.java
@@ -54,163 +54,87 @@ public class StandardFileSystemManager extends DefaultFileSystemManager {
     private ClassLoader classLoader;
 
     /**
-     * Sets the configuration file for this manager.
+     * Adds an extension map.
      *
-     * @param configUri The URI for this manager.
+     * @param map containing the Elements.
      */
-    public void setConfiguration(final String configUri) {
-        try {
-            setConfiguration(new URL(configUri));
-        } catch (final MalformedURLException e) {
-            getLogger().warn(e.getLocalizedMessage(), e);
+    private void addExtensionMap(final Element map) {
+        final String extension = map.getAttribute("extension");
+        final String scheme = map.getAttribute("scheme");
+        if (!StringUtils.isEmpty(scheme)) {
+            addExtensionMap(extension, scheme);
         }
     }
 
     /**
-     * Sets the configuration file for this manager.
-     *
-     * @param configUri The URI forthis manager.
-     */
-    public void setConfiguration(final URL configUri) {
-        this.configUri = configUri;
-    }
-
-    /**
-     * Sets the ClassLoader to use to load the providers. Default is to use the ClassLoader that loaded this class.
+     * Adds a mime-type map.
      *
-     * @param classLoader The ClassLoader.
+     * @param map containing the Elements.
      */
-    public void setClassLoader(final ClassLoader classLoader) {
-        this.classLoader = classLoader;
+    private void addMimeTypeMap(final Element map) {
+        final String mimeType = map.getAttribute("mime-type");
+        final String scheme = map.getAttribute("scheme");
+        addMimeTypeMap(mimeType, scheme);
     }
 
     /**
-     * Initializes this manager. Adds the providers and replicator.
-     *
-     * @throws FileSystemException if an error occurs.
+     * Adds a operationProvider from a operationProvider definition.
      */
-    @Override
-    public void init() throws FileSystemException {
-        // Set the replicator and temporary file store (use the same component)
-        final DefaultFileReplicator replicator = createDefaultFileReplicator();
-        setReplicator(new PrivilegedFileReplicator(replicator));
-        setTemporaryFileStore(replicator);
+    private void addOperationProvider(final Element providerDef) throws FileSystemException {
+        final String classname = providerDef.getAttribute("class-name");
 
-        if (configUri == null) {
-            // Use default config
-            final URL url = getClass().getResource(CONFIG_RESOURCE);
-            FileSystemException.requireNonNull(url, "vfs.impl/find-config-file.error", CONFIG_RESOURCE);
-            configUri = url;
+        // Attach only to available schemas
+        final String[] schemas = getSchemas(providerDef);
+        for (final String schema : schemas) {
+            if (hasProvider(schema)) {
+                final FileOperationProvider operationProvider = (FileOperationProvider) createInstance(classname);
+                addOperationProvider(schema, operationProvider);
+            }
         }
-
-        configure(configUri);
-        configurePlugins();
-
-        // Initialize super-class
-        super.init();
     }
 
     /**
-     * Scans the classpath to find any droped plugin.
-     * <p>
-     * The plugin-description has to be in {@code /META-INF/vfs-providers.xml}.
-     * </p>
+     * Adds a provider from a provider definition.
      *
+     * @param providerDef the provider definition
+     * @param isDefault true if the default should be used.
      * @throws FileSystemException if an error occurs.
      */
-    protected void configurePlugins() throws FileSystemException {
-        final Enumeration<URL> enumResources;
-        try {
-            enumResources = enumerateResources(PLUGIN_CONFIG_RESOURCE);
-        } catch (final IOException e) {
-            throw new FileSystemException(e);
-        }
-
-        while (enumResources.hasMoreElements()) {
-            configure(enumResources.nextElement());
-        }
-    }
+    private void addProvider(final Element providerDef, final boolean isDefault) throws FileSystemException {
+        final String classname = providerDef.getAttribute("class-name");
 
-    /**
-     * Returns a class loader or null since some Java implementation is null for the bootstrap class loader.
-     *
-     * @return A class loader or null since some Java implementation is null for the bootstrap class loader.
-     */
-    private ClassLoader findClassLoader() {
-        if (classLoader != null) {
-            return classLoader;
-        }
-        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
-        if (cl != null) {
-            return cl;
+        // Make sure all required schemes are available
+        final String[] requiredSchemes = getRequiredSchemes(providerDef);
+        for (final String requiredScheme : requiredSchemes) {
+            if (!hasProvider(requiredScheme)) {
+                final String msg = Messages.getString("vfs.impl/skipping-provider-scheme.debug", classname,
+                        requiredScheme);
+                VfsLog.debug(getLogger(), getLogger(), msg);
+                return;
+            }
         }
-        return getValidClassLoader(getClass());
-    }
-
-    protected DefaultFileReplicator createDefaultFileReplicator() {
-        return new DefaultFileReplicator();
-    }
-
-    /**
-     * Configures this manager from an XML configuration file.
-     *
-     * @param configUri The URI of the configuration.
-     * @throws FileSystemException if an error occus.
-     */
-    private void configure(final URL configUri) throws FileSystemException {
-        InputStream configStream = null;
-        try {
-            // Load up the config
-            // TODO - validate
-            final DocumentBuilder builder = createDocumentBuilder();
-            configStream = configUri.openStream();
-            final Element config = builder.parse(configStream).getDocumentElement();
 
-            configure(config);
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.impl/load-config.error", configUri.toString(), e);
-        } finally {
-            if (configStream != null) {
-                try {
-                    configStream.close();
-                } catch (final IOException e) {
-                    getLogger().warn(e.getLocalizedMessage(), e);
-                }
+        // Make sure all required classes are in classpath
+        final String[] requiredClasses = getRequiredClasses(providerDef);
+        for (final String requiredClass : requiredClasses) {
+            if (!findClass(requiredClass)) {
+                final String msg = Messages.getString("vfs.impl/skipping-provider.debug", classname, requiredClass);
+                VfsLog.debug(getLogger(), getLogger(), msg);
+                return;
             }
         }
-    }
-
-    /**
-     * Configures this manager from an XML configuration file.
-     *
-     * @param configUri The URI of the configuration.
-     * @param configStream An InputStream containing the configuration.
-     * @throws FileSystemException if an error occurs.
-     */
-    @SuppressWarnings("unused")
-    private void configure(final String configUri, final InputStream configStream) throws FileSystemException {
-        try {
-            // Load up the config
-            // TODO - validate
-            configure(createDocumentBuilder().parse(configStream).getDocumentElement());
 
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.impl/load-config.error", configUri, e);
+        // Create and register the provider
+        final FileProvider provider = (FileProvider) createInstance(classname);
+        final String[] schemas = getSchemas(providerDef);
+        if (schemas.length > 0) {
+            addProvider(schemas, provider);
         }
-    }
 
-    /**
-     * Configure and create a DocumentBuilder
-     *
-     * @return A DocumentBuilder for the configuration.
-     * @throws ParserConfigurationException if an error occurs.
-     */
-    private DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
-        final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setIgnoringElementContentWhitespace(true);
-        factory.setIgnoringComments(true);
-        factory.setExpandEntityReferences(true);
-        return factory.newDocumentBuilder();
+        // Set as default, if required
+        if (isDefault) {
+            setDefaultProvider(provider);
+        }
     }
 
     /**
@@ -258,87 +182,115 @@ public class StandardFileSystemManager extends DefaultFileSystemManager {
     }
 
     /**
-     * Adds an extension map.
+     * Configures this manager from an XML configuration file.
      *
-     * @param map containing the Elements.
+     * @param configUri The URI of the configuration.
+     * @param configStream An InputStream containing the configuration.
+     * @throws FileSystemException if an error occurs.
      */
-    private void addExtensionMap(final Element map) {
-        final String extension = map.getAttribute("extension");
-        final String scheme = map.getAttribute("scheme");
-        if (!StringUtils.isEmpty(scheme)) {
-            addExtensionMap(extension, scheme);
+    @SuppressWarnings("unused")
+    private void configure(final String configUri, final InputStream configStream) throws FileSystemException {
+        try {
+            // Load up the config
+            // TODO - validate
+            configure(createDocumentBuilder().parse(configStream).getDocumentElement());
+
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.impl/load-config.error", configUri, e);
         }
     }
 
     /**
-     * Adds a mime-type map.
+     * Configures this manager from an XML configuration file.
      *
-     * @param map containing the Elements.
+     * @param configUri The URI of the configuration.
+     * @throws FileSystemException if an error occus.
      */
-    private void addMimeTypeMap(final Element map) {
-        final String mimeType = map.getAttribute("mime-type");
-        final String scheme = map.getAttribute("scheme");
-        addMimeTypeMap(mimeType, scheme);
+    private void configure(final URL configUri) throws FileSystemException {
+        InputStream configStream = null;
+        try {
+            // Load up the config
+            // TODO - validate
+            final DocumentBuilder builder = createDocumentBuilder();
+            configStream = configUri.openStream();
+            final Element config = builder.parse(configStream).getDocumentElement();
+
+            configure(config);
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.impl/load-config.error", configUri.toString(), e);
+        } finally {
+            if (configStream != null) {
+                try {
+                    configStream.close();
+                } catch (final IOException e) {
+                    getLogger().warn(e.getLocalizedMessage(), e);
+                }
+            }
+        }
     }
 
     /**
-     * Adds a provider from a provider definition.
+     * Scans the classpath to find any droped plugin.
+     * <p>
+     * The plugin-description has to be in {@code /META-INF/vfs-providers.xml}.
+     * </p>
      *
-     * @param providerDef the provider definition
-     * @param isDefault true if the default should be used.
      * @throws FileSystemException if an error occurs.
      */
-    private void addProvider(final Element providerDef, final boolean isDefault) throws FileSystemException {
-        final String classname = providerDef.getAttribute("class-name");
-
-        // Make sure all required schemes are available
-        final String[] requiredSchemes = getRequiredSchemes(providerDef);
-        for (final String requiredScheme : requiredSchemes) {
-            if (!hasProvider(requiredScheme)) {
-                final String msg = Messages.getString("vfs.impl/skipping-provider-scheme.debug", classname,
-                        requiredScheme);
-                VfsLog.debug(getLogger(), getLogger(), msg);
-                return;
-            }
+    protected void configurePlugins() throws FileSystemException {
+        final Enumeration<URL> enumResources;
+        try {
+            enumResources = enumerateResources(PLUGIN_CONFIG_RESOURCE);
+        } catch (final IOException e) {
+            throw new FileSystemException(e);
         }
 
-        // Make sure all required classes are in classpath
-        final String[] requiredClasses = getRequiredClasses(providerDef);
-        for (final String requiredClass : requiredClasses) {
-            if (!findClass(requiredClass)) {
-                final String msg = Messages.getString("vfs.impl/skipping-provider.debug", classname, requiredClass);
-                VfsLog.debug(getLogger(), getLogger(), msg);
-                return;
-            }
+        while (enumResources.hasMoreElements()) {
+            configure(enumResources.nextElement());
         }
+    }
 
-        // Create and register the provider
-        final FileProvider provider = (FileProvider) createInstance(classname);
-        final String[] schemas = getSchemas(providerDef);
-        if (schemas.length > 0) {
-            addProvider(schemas, provider);
-        }
+    protected DefaultFileReplicator createDefaultFileReplicator() {
+        return new DefaultFileReplicator();
+    }
 
-        // Set as default, if required
-        if (isDefault) {
-            setDefaultProvider(provider);
-        }
+    /**
+     * Configure and create a DocumentBuilder
+     *
+     * @return A DocumentBuilder for the configuration.
+     * @throws ParserConfigurationException if an error occurs.
+     */
+    private DocumentBuilder createDocumentBuilder() throws ParserConfigurationException {
+        final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        factory.setExpandEntityReferences(true);
+        return factory.newDocumentBuilder();
     }
 
     /**
-     * Adds a operationProvider from a operationProvider definition.
+     * Creates a provider.
      */
-    private void addOperationProvider(final Element providerDef) throws FileSystemException {
-        final String classname = providerDef.getAttribute("class-name");
+    private Object createInstance(final String className) throws FileSystemException {
+        try {
+            return loadClass(className).newInstance();
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.impl/create-provider.error", className, e);
+        }
+    }
 
-        // Attach only to available schemas
-        final String[] schemas = getSchemas(providerDef);
-        for (final String schema : schemas) {
-            if (hasProvider(schema)) {
-                final FileOperationProvider operationProvider = (FileOperationProvider) createInstance(classname);
-                addOperationProvider(schema, operationProvider);
-            }
+    /**
+     * Enumerates resources from different class loaders.
+     *
+     * @throws IOException if {@code getResource} failed.
+     * @see #findClassLoader()
+     */
+    private Enumeration<URL> enumerateResources(final String name) throws IOException {
+        Enumeration<URL> enumeration = findClassLoader().getResources(name);
+        if (enumeration == null || !enumeration.hasMoreElements()) {
+            enumeration = getValidClassLoader(getClass()).getResources(name);
         }
+        return enumeration;
     }
 
     /**
@@ -354,6 +306,22 @@ public class StandardFileSystemManager extends DefaultFileSystemManager {
     }
 
     /**
+     * Returns a class loader or null since some Java implementation is null for the bootstrap class loader.
+     *
+     * @return A class loader or null since some Java implementation is null for the bootstrap class loader.
+     */
+    private ClassLoader findClassLoader() {
+        if (classLoader != null) {
+            return classLoader;
+        }
+        final ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl != null) {
+            return cl;
+        }
+        return getValidClassLoader(getClass());
+    }
+
+    /**
      * Extracts the required classes from a provider definition.
      */
     private String[] getRequiredClasses(final Element providerDef) {
@@ -405,20 +373,30 @@ public class StandardFileSystemManager extends DefaultFileSystemManager {
         return validateClassLoader(clazz.getClassLoader(), clazz);
     }
 
-    private ClassLoader validateClassLoader(final ClassLoader clazzLoader, final Class<?> clazz) {
-        return Objects.requireNonNull(clazzLoader, "The class loader for " + clazz
-                + " is null; some Java implementions use null for the bootstrap class loader.");
-    }
-
     /**
-     * Creates a provider.
+     * Initializes this manager. Adds the providers and replicator.
+     *
+     * @throws FileSystemException if an error occurs.
      */
-    private Object createInstance(final String className) throws FileSystemException {
-        try {
-            return loadClass(className).newInstance();
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.impl/create-provider.error", className, e);
+    @Override
+    public void init() throws FileSystemException {
+        // Set the replicator and temporary file store (use the same component)
+        final DefaultFileReplicator replicator = createDefaultFileReplicator();
+        setReplicator(new PrivilegedFileReplicator(replicator));
+        setTemporaryFileStore(replicator);
+
+        if (configUri == null) {
+            // Use default config
+            final URL url = getClass().getResource(CONFIG_RESOURCE);
+            FileSystemException.requireNonNull(url, "vfs.impl/find-config-file.error", CONFIG_RESOURCE);
+            configUri = url;
         }
+
+        configure(configUri);
+        configurePlugins();
+
+        // Initialize super-class
+        super.init();
     }
 
     /**
@@ -436,17 +414,39 @@ public class StandardFileSystemManager extends DefaultFileSystemManager {
     }
 
     /**
-     * Enumerates resources from different class loaders.
+     * Sets the ClassLoader to use to load the providers. Default is to use the ClassLoader that loaded this class.
      *
-     * @throws IOException if {@code getResource} failed.
-     * @see #findClassLoader()
+     * @param classLoader The ClassLoader.
      */
-    private Enumeration<URL> enumerateResources(final String name) throws IOException {
-        Enumeration<URL> enumeration = findClassLoader().getResources(name);
-        if (enumeration == null || !enumeration.hasMoreElements()) {
-            enumeration = getValidClassLoader(getClass()).getResources(name);
+    public void setClassLoader(final ClassLoader classLoader) {
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Sets the configuration file for this manager.
+     *
+     * @param configUri The URI for this manager.
+     */
+    public void setConfiguration(final String configUri) {
+        try {
+            setConfiguration(new URL(configUri));
+        } catch (final MalformedURLException e) {
+            getLogger().warn(e.getLocalizedMessage(), e);
         }
-        return enumeration;
+    }
+
+    /**
+     * Sets the configuration file for this manager.
+     *
+     * @param configUri The URI forthis manager.
+     */
+    public void setConfiguration(final URL configUri) {
+        this.configUri = configUri;
+    }
+
+    private ClassLoader validateClassLoader(final ClassLoader clazzLoader, final Class<?> clazz) {
+        return Objects.requireNonNull(clazzLoader, "The class loader for " + clazz
+                + " is null; some Java implementions use null for the bootstrap class loader.");
     }
 
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java
index c9a9b2b..27df9ad 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/SynchronizedFileObject.java
@@ -89,17 +89,17 @@ public class SynchronizedFileObject extends DecoratedFileObject {
     }
 
     @Override
-    public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
-            throws FileSystemException {
+    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
         synchronized (this) {
-            super.findFiles(selector, depthwise, selected);
+            return super.findFiles(selector);
         }
     }
 
     @Override
-    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
+    public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
+            throws FileSystemException {
         synchronized (this) {
-            return super.findFiles(selector);
+            super.findFiles(selector, depthwise, selected);
         }
     }
 
@@ -132,6 +132,13 @@ public class SynchronizedFileObject extends DecoratedFileObject {
     }
 
     @Override
+    public boolean isExecutable() throws FileSystemException {
+        synchronized (this) {
+            return super.isExecutable();
+        }
+    }
+
+    @Override
     public boolean isHidden() throws FileSystemException {
         synchronized (this) {
             return super.isHidden();
@@ -153,23 +160,23 @@ public class SynchronizedFileObject extends DecoratedFileObject {
     }
 
     @Override
-    public boolean isExecutable() throws FileSystemException {
+    public void moveTo(final FileObject destFile) throws FileSystemException {
         synchronized (this) {
-            return super.isExecutable();
+            super.moveTo(destFile);
         }
     }
 
     @Override
-    public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
+    public FileObject resolveFile(final String path) throws FileSystemException {
         synchronized (this) {
-            return super.setReadable(readable, ownerOnly);
+            return super.resolveFile(path);
         }
     }
 
     @Override
-    public boolean setWritable(final boolean writable, final boolean ownerOnly) throws FileSystemException {
+    public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
         synchronized (this) {
-            return super.setWritable(writable, ownerOnly);
+            return super.resolveFile(name, scope);
         }
     }
 
@@ -181,23 +188,16 @@ public class SynchronizedFileObject extends DecoratedFileObject {
     }
 
     @Override
-    public void moveTo(final FileObject destFile) throws FileSystemException {
-        synchronized (this) {
-            super.moveTo(destFile);
-        }
-    }
-
-    @Override
-    public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
+    public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
         synchronized (this) {
-            return super.resolveFile(name, scope);
+            return super.setReadable(readable, ownerOnly);
         }
     }
 
     @Override
-    public FileObject resolveFile(final String path) throws FileSystemException {
+    public boolean setWritable(final boolean writable, final boolean ownerOnly) throws FileSystemException {
         synchronized (this) {
-            return super.resolveFile(path);
+            return super.setWritable(writable, ownerOnly);
         }
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VFSClassLoader.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VFSClassLoader.java
index 3ab96f7..39faa39 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VFSClassLoader.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VFSClassLoader.java
@@ -103,16 +103,6 @@ public class VFSClassLoader extends SecureClassLoader {
     }
 
     /**
-     * Provide access to the file objects this class loader represents.
-     *
-     * @return An array of FileObjects.
-     * @since 2.0
-     */
-    public FileObject[] getFileObjects() {
-        return resources.toArray(FileObject.EMPTY_ARRAY);
-    }
-
-    /**
      * Appends the specified FileObjects to the list of FileObjects to search for classes and resources.
      *
      * @param manager The FileSystemManager.
@@ -137,21 +127,15 @@ public class VFSClassLoader extends SecureClassLoader {
     }
 
     /**
-     * Finds and loads the class with the specified name from the search path.
+     * Copies the permissions from src to dest.
      *
-     * @throws ClassNotFoundException if the class is not found.
+     * @param src The source PermissionCollection.
+     * @param dest The destination PermissionCollection.
      */
-    @Override
-    protected Class<?> findClass(final String name) throws ClassNotFoundException {
-        try {
-            final String path = name.replace('.', '/').concat(".class");
-            final Resource res = loadResource(path);
-            if (res == null) {
-                throw new ClassNotFoundException(name);
-            }
-            return defineClass(name, res);
-        } catch (final IOException ioe) {
-            throw new ClassNotFoundException(name, ioe);
+    protected void copyPermissions(final PermissionCollection src, final PermissionCollection dest) {
+        for (final Enumeration<Permission> elem = src.elements(); elem.hasMoreElements();) {
+            final Permission permission = elem.nextElement();
+            dest.add(permission);
         }
     }
 
@@ -183,14 +167,6 @@ public class VFSClassLoader extends SecureClassLoader {
     }
 
     /**
-     * Returns true if the we should seal the package where res resides.
-     */
-    private boolean isSealed(final Resource res) throws FileSystemException {
-        final String sealed = res.getPackageAttribute(Attributes.Name.SEALED);
-        return "true".equalsIgnoreCase(sealed);
-    }
-
-    /**
      * Reads attributes for the package and defines it.
      */
     private Package definePackage(final String name, final Resource res) throws FileSystemException {
@@ -213,64 +189,22 @@ public class VFSClassLoader extends SecureClassLoader {
     }
 
     /**
-     * Calls super.getPermissions both for the code source and also adds the permissions granted to the parent layers.
+     * Finds and loads the class with the specified name from the search path.
      *
-     * @param cs the CodeSource.
-     * @return The PermissionCollections.
+     * @throws ClassNotFoundException if the class is not found.
      */
     @Override
-    protected PermissionCollection getPermissions(final CodeSource cs) {
+    protected Class<?> findClass(final String name) throws ClassNotFoundException {
         try {
-            final String url = cs.getLocation().toString();
-            final FileObject file = lookupFileObject(url);
-            if (file == null) {
-                return super.getPermissions(cs);
-            }
-
-            final FileObject parentLayer = file.getFileSystem().getParentLayer();
-            if (parentLayer == null) {
-                return super.getPermissions(cs);
-            }
-
-            final Permissions combi = new Permissions();
-            PermissionCollection permCollect = super.getPermissions(cs);
-            copyPermissions(permCollect, combi);
-
-            for (FileObject parent = parentLayer; parent != null; parent = parent.getFileSystem().getParentLayer()) {
-                final CodeSource parentcs = new CodeSource(parent.getURL(), parent.getContent().getCertificates());
-                permCollect = super.getPermissions(parentcs);
-                copyPermissions(permCollect, combi);
-            }
-
-            return combi;
-        } catch (final FileSystemException fse) {
-            throw new SecurityException(fse.getMessage());
-        }
-    }
-
-    /**
-     * Copies the permissions from src to dest.
-     *
-     * @param src The source PermissionCollection.
-     * @param dest The destination PermissionCollection.
-     */
-    protected void copyPermissions(final PermissionCollection src, final PermissionCollection dest) {
-        for (final Enumeration<Permission> elem = src.elements(); elem.hasMoreElements();) {
-            final Permission permission = elem.nextElement();
-            dest.add(permission);
-        }
-    }
-
-    /**
-     * Does a reverse lookup to find the FileObject when we only have the URL.
-     */
-    private FileObject lookupFileObject(final String name) {
-        for (final FileObject object : resources) {
-            if (name.equals(object.getName().getURI())) {
-                return object;
+            final String path = name.replace('.', '/').concat(".class");
+            final Resource res = loadResource(path);
+            if (res == null) {
+                throw new ClassNotFoundException(name);
             }
+            return defineClass(name, res);
+        } catch (final IOException ioe) {
+            throw new ClassNotFoundException(name, ioe);
         }
-        return null;
     }
 
     /**
@@ -317,6 +251,60 @@ public class VFSClassLoader extends SecureClassLoader {
     }
 
     /**
+     * Provide access to the file objects this class loader represents.
+     *
+     * @return An array of FileObjects.
+     * @since 2.0
+     */
+    public FileObject[] getFileObjects() {
+        return resources.toArray(FileObject.EMPTY_ARRAY);
+    }
+
+    /**
+     * Calls super.getPermissions both for the code source and also adds the permissions granted to the parent layers.
+     *
+     * @param cs the CodeSource.
+     * @return The PermissionCollections.
+     */
+    @Override
+    protected PermissionCollection getPermissions(final CodeSource cs) {
+        try {
+            final String url = cs.getLocation().toString();
+            final FileObject file = lookupFileObject(url);
+            if (file == null) {
+                return super.getPermissions(cs);
+            }
+
+            final FileObject parentLayer = file.getFileSystem().getParentLayer();
+            if (parentLayer == null) {
+                return super.getPermissions(cs);
+            }
+
+            final Permissions combi = new Permissions();
+            PermissionCollection permCollect = super.getPermissions(cs);
+            copyPermissions(permCollect, combi);
+
+            for (FileObject parent = parentLayer; parent != null; parent = parent.getFileSystem().getParentLayer()) {
+                final CodeSource parentcs = new CodeSource(parent.getURL(), parent.getContent().getCertificates());
+                permCollect = super.getPermissions(parentcs);
+                copyPermissions(permCollect, combi);
+            }
+
+            return combi;
+        } catch (final FileSystemException fse) {
+            throw new SecurityException(fse.getMessage());
+        }
+    }
+
+    /**
+     * Returns true if the we should seal the package where res resides.
+     */
+    private boolean isSealed(final Resource res) throws FileSystemException {
+        final String sealed = res.getPackageAttribute(Attributes.Name.SEALED);
+        return "true".equalsIgnoreCase(sealed);
+    }
+
+    /**
      * Searches through the search path of for the first class or resource with specified name.
      *
      * @param name The resource to load.
@@ -333,4 +321,16 @@ public class VFSClassLoader extends SecureClassLoader {
         }
         return null;
     }
+
+    /**
+     * Does a reverse lookup to find the FileObject when we only have the URL.
+     */
+    private FileObject lookupFileObject(final String name) {
+        for (final FileObject object : resources) {
+            if (name.equals(object.getName().getURI())) {
+                return object;
+            }
+        }
+        return null;
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileName.java
index 16a2b33..338f887 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileName.java
@@ -37,12 +37,12 @@ public class VirtualFileName extends AbstractFileName {
     }
 
     @Override
-    public FileName createName(final String absolutePath, final FileType type) {
-        return new VirtualFileName(getScheme(), absolutePath, type);
+    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
+        buffer.append(getScheme());
     }
 
     @Override
-    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
-        buffer.append(getScheme());
+    public FileName createName(final String absolutePath, final FileType type) {
+        return new VirtualFileName(getScheme(), absolutePath, type);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileProvider.java
index a817bfc..9687d48 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileProvider.java
@@ -31,6 +31,21 @@ import org.apache.commons.vfs2.provider.AbstractVfsContainer;
 public class VirtualFileProvider extends AbstractVfsContainer {
 
     /**
+     * Close a VirtualFileSystem by removing it from the {@code #components} list of this provider.
+     * <p>
+     * This gets called from DefaultFileManager#_closeFileSystem.
+     * </p>
+     *
+     * @param fileSystem the file system remembered by this provider.
+     */
+    void closeFileSystem(final FileSystem fileSystem) {
+        final AbstractFileSystem fs = (AbstractFileSystem) fileSystem;
+
+        removeComponent(fs);
+        fs.close();
+    }
+
+    /**
      * Creates a virtual file system, with the supplied file as its root.
      *
      * @param rootFile The root of the file system.
@@ -59,19 +74,4 @@ public class VirtualFileProvider extends AbstractVfsContainer {
         addComponent(fs);
         return fs.getRoot();
     }
-
-    /**
-     * Close a VirtualFileSystem by removing it from the {@code #components} list of this provider.
-     * <p>
-     * This gets called from DefaultFileManager#_closeFileSystem.
-     * </p>
-     *
-     * @param fileSystem the file system remembered by this provider.
-     */
-    void closeFileSystem(final FileSystem fileSystem) {
-        final AbstractFileSystem fs = (AbstractFileSystem) fileSystem;
-
-        removeComponent(fs);
-        fs.close();
-    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileSystem.java
index 777e0be..59e2afe 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/impl/VirtualFileSystem.java
@@ -72,27 +72,6 @@ public class VirtualFileSystem extends AbstractFileSystem {
     }
 
     /**
-     * Creates a file object. This method is called only if the requested file is not cached.
-     */
-    @Override
-    protected FileObject createFile(final AbstractFileName name) throws Exception {
-        // Find the file that the name points to
-        final FileName junctionPoint = getJunctionForFile(name);
-        final FileObject file;
-        if (junctionPoint != null) {
-            // Resolve the real file
-            final FileObject junctionFile = junctions.get(junctionPoint);
-            final String relName = junctionPoint.getRelativeName(name);
-            file = junctionFile.resolveFile(relName, NameScope.DESCENDENT_OR_SELF);
-        } else {
-            file = null;
-        }
-
-        // Return a wrapper around the file
-        return new DelegateFileObject(name, this, file);
-    }
-
-    /**
      * Adds a junction to this file system.
      *
      * @param junctionPoint The location of the junction.
@@ -142,19 +121,31 @@ public class VirtualFileSystem extends AbstractFileSystem {
         }
     }
 
+    @Override
+    public void close() {
+        super.close();
+        junctions.clear();
+    }
+
     /**
-     * Removes a junction from this file system.
-     *
-     * @param junctionPoint The junction to remove.
-     * @throws FileSystemException if an error occurs.
+     * Creates a file object. This method is called only if the requested file is not cached.
      */
     @Override
-    public void removeJunction(final String junctionPoint) throws FileSystemException {
-        final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
-        junctions.remove(junctionName);
+    protected FileObject createFile(final AbstractFileName name) throws Exception {
+        // Find the file that the name points to
+        final FileName junctionPoint = getJunctionForFile(name);
+        final FileObject file;
+        if (junctionPoint != null) {
+            // Resolve the real file
+            final FileObject junctionFile = junctions.get(junctionPoint);
+            final String relName = junctionPoint.getRelativeName(name);
+            file = junctionFile.resolveFile(relName, NameScope.DESCENDENT_OR_SELF);
+        } else {
+            file = null;
+        }
 
-        // TODO - remove from parents of junction point
-        // TODO - detach all cached children of the junction point from their real file
+        // Return a wrapper around the file
+        return new DelegateFileObject(name, this, file);
     }
 
     /**
@@ -180,9 +171,18 @@ public class VirtualFileSystem extends AbstractFileSystem {
         return null;
     }
 
+    /**
+     * Removes a junction from this file system.
+     *
+     * @param junctionPoint The junction to remove.
+     * @throws FileSystemException if an error occurs.
+     */
     @Override
-    public void close() {
-        super.close();
-        junctions.clear();
+    public void removeJunction(final String junctionPoint) throws FileSystemException {
+        final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
+        junctions.remove(junctionName);
+
+        // TODO - remove from parents of junction point
+        // TODO - detach all cached children of the junction point from their real file
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/AbstractFileOperationProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/AbstractFileOperationProvider.java
index 977bc3c..c88b510 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/AbstractFileOperationProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/AbstractFileOperationProvider.java
@@ -36,6 +36,22 @@ public abstract class AbstractFileOperationProvider implements FileOperationProv
     private final Collection<Class<? extends FileOperation>> operations = new ArrayList<>();
 
     /**
+     * Add new FileOperation to list of known operations.
+     *
+     * @param operationClass a class implementing FileOperation.
+     * @throws FileSystemException if instances of the class cannot be assigned to FileOperation.
+     */
+    protected final void addOperation(final Class<? extends FileOperation> operationClass) throws FileSystemException {
+        // check validity of passed class
+        if (!FileOperation.class.isAssignableFrom(operationClass)) {
+            throw new FileSystemException("vfs.operation/cant-register.error", operationClass);
+        }
+
+        // ok, lets add it to the list
+        operations.add(operationClass);
+    }
+
+    /**
      * Gather available operations for the specified FileObject and put them into specified operationsList.
      *
      * @param operationsList the list of available operations for the specified FileObject. The operationList contains
@@ -112,20 +128,4 @@ public abstract class AbstractFileOperationProvider implements FileOperationProv
 
         return foundClass;
     }
-
-    /**
-     * Add new FileOperation to list of known operations.
-     *
-     * @param operationClass a class implementing FileOperation.
-     * @throws FileSystemException if instances of the class cannot be assigned to FileOperation.
-     */
-    protected final void addOperation(final Class<? extends FileOperation> operationClass) throws FileSystemException {
-        // check validity of passed class
-        if (!FileOperation.class.isAssignableFrom(operationClass)) {
-            throw new FileSystemException("vfs.operation/cant-register.error", operationClass);
-        }
-
-        // ok, lets add it to the list
-        operations.add(operationClass);
-    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/DefaultFileOperations.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/DefaultFileOperations.java
index 7a76d7e..92ff3ee 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/DefaultFileOperations.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/DefaultFileOperations.java
@@ -47,55 +47,55 @@ public class DefaultFileOperations implements FileOperations {
     }
 
     /**
-     * @return The operation classes.
-     * @throws FileSystemException If an error occurs.
+     * @param operationClass The Class that performs the operation.
+     * @return The FileOperation.
+     * @throws FileSystemException if an error occurs.
      */
     @Override
-    public Class<? extends FileOperation>[] getOperations() throws FileSystemException {
+    public FileOperation getOperation(final Class<? extends FileOperation> operationClass) throws FileSystemException {
 
         final String scheme = fileObject.getURL().getProtocol();
         final FileOperationProvider[] providers = fsmanager.getOperationProviders(scheme);
 
-        if (providers == null) {
-            return null;
-        }
+        FileSystemException.requireNonNull(providers, "vfs.operation/operation-not-supported.error", operationClass);
 
-        final List<Class<? extends FileOperation>> operations = new ArrayList<>();
+        FileOperation resultOperation = null;
 
         for (final FileOperationProvider provider : providers) {
-            provider.collectOperations(operations, fileObject);
+            resultOperation = provider.getOperation(fileObject, operationClass);
+
+            if (resultOperation != null) {
+                break;
+            }
         }
 
-        @SuppressWarnings("unchecked")
-        final Class<? extends FileOperation>[] array = (Class<? extends FileOperation>[]) operations
-                .toArray(new Class<?>[] {});
-        return array;
+        return FileSystemException.requireNonNull(resultOperation, "vfs.operation/operation-not-supported.error", operationClass);
     }
 
     /**
-     * @param operationClass The Class that performs the operation.
-     * @return The FileOperation.
-     * @throws FileSystemException if an error occurs.
+     * @return The operation classes.
+     * @throws FileSystemException If an error occurs.
      */
     @Override
-    public FileOperation getOperation(final Class<? extends FileOperation> operationClass) throws FileSystemException {
+    public Class<? extends FileOperation>[] getOperations() throws FileSystemException {
 
         final String scheme = fileObject.getURL().getProtocol();
         final FileOperationProvider[] providers = fsmanager.getOperationProviders(scheme);
 
-        FileSystemException.requireNonNull(providers, "vfs.operation/operation-not-supported.error", operationClass);
+        if (providers == null) {
+            return null;
+        }
 
-        FileOperation resultOperation = null;
+        final List<Class<? extends FileOperation>> operations = new ArrayList<>();
 
         for (final FileOperationProvider provider : providers) {
-            resultOperation = provider.getOperation(fileObject, operationClass);
-
-            if (resultOperation != null) {
-                break;
-            }
+            provider.collectOperations(operations, fileObject);
         }
 
-        return FileSystemException.requireNonNull(resultOperation, "vfs.operation/operation-not-supported.error", operationClass);
+        @SuppressWarnings("unchecked")
+        final Class<? extends FileOperation>[] array = (Class<? extends FileOperation>[]) operations
+                .toArray(new Class<?>[] {});
+        return array;
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/FileOperations.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/FileOperations.java
index d651c76..ede7948 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/FileOperations.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/FileOperations.java
@@ -27,12 +27,6 @@ import org.apache.commons.vfs2.FileSystemException;
  */
 public interface FileOperations {
     /**
-     * @return all operations associated with the fileObject
-     * @throws FileSystemException if an error occurs.
-     */
-    Class<? extends FileOperation>[] getOperations() throws FileSystemException;
-
-    /**
      * @param operationClass the operation Class.
      * @return a operation implementing the given {@code operationClass}
      * @throws FileSystemException if an error occus.
@@ -40,6 +34,12 @@ public interface FileOperations {
     FileOperation getOperation(Class<? extends FileOperation> operationClass) throws FileSystemException;
 
     /**
+     * @return all operations associated with the fileObject
+     * @throws FileSystemException if an error occurs.
+     */
+    Class<? extends FileOperation>[] getOperations() throws FileSystemException;
+
+    /**
      * @param operationClass the operation Class.
      * @return if a operation {@code operationClass} is available
      * @throws FileSystemException if an error ocurs.
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCheckout.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCheckout.java
index 9167963..e14cc12 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCheckout.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCheckout.java
@@ -26,10 +26,10 @@ import org.apache.commons.vfs2.operations.FileOperation;
 public interface VcsCheckout extends FileOperation {
 
     /**
-     *
-     * @param revision The revision number.
+     * @param export if true, administrative .svn directoies will not be created on the retrieved tree. The checkout
+     *        operation in this case is equivalent to export function.
      */
-    void setRevision(long revision);
+    void setExport(boolean export);
 
     /**
      *
@@ -39,13 +39,13 @@ public interface VcsCheckout extends FileOperation {
 
     /**
      *
-     * @param targetDir directory under which retrieved files should be placed.
+     * @param revision The revision number.
      */
-    void setTargetDirectory(FileObject targetDir);
+    void setRevision(long revision);
 
     /**
-     * @param export if true, administrative .svn directoies will not be created on the retrieved tree. The checkout
-     *        operation in this case is equivalent to export function.
+     *
+     * @param targetDir directory under which retrieved files should be placed.
      */
-    void setExport(boolean export);
+    void setTargetDirectory(FileObject targetDir);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCommit.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCommit.java
index b4a8765..4e61eb4 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCommit.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsCommit.java
@@ -26,25 +26,25 @@ public interface VcsCommit extends FileOperation {
 
     /**
      *
-     * @param isRecursive true if directories should be traversed.
+     * @param listener Listener that is given control when a commit occurs.
      */
-    void setRecursive(boolean isRecursive);
+    void addCommitListener(VcsCommitListener listener);
 
     /**
      *
-     * @param message The message.
+     * @param listener The Listener.
      */
-    void setMessage(String message);
+    void removeCommitListener(VcsCommitListener listener);
 
     /**
      *
-     * @param listener Listener that is given control when a commit occurs.
+     * @param message The message.
      */
-    void addCommitListener(VcsCommitListener listener);
+    void setMessage(String message);
 
     /**
      *
-     * @param listener The Listener.
+     * @param isRecursive true if directories should be traversed.
      */
-    void removeCommitListener(VcsCommitListener listener);
+    void setRecursive(boolean isRecursive);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLog.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLog.java
index 1cbfbd3..7ec907d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLog.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLog.java
@@ -26,12 +26,6 @@ public interface VcsLog extends FileOperation {
 
     /**
      *
-     * @param startRev The start revision.
-     */
-    void setStartRevision(long startRev);
-
-    /**
-     *
      * @param endRev The end revision.
      */
     void setEndRevision(long endRev);
@@ -41,4 +35,10 @@ public interface VcsLog extends FileOperation {
      * @param handler The LogEntry handler.
      */
     void setLogEntryHandler(VcsLogEntryHandler handler);
+
+    /**
+     *
+     * @param startRev The start revision.
+     */
+    void setStartRevision(long startRev);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLogEntry.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLogEntry.java
index 358d342..d3e082d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLogEntry.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsLogEntry.java
@@ -75,10 +75,10 @@ public class VcsLogEntry {
 
     /**
      *
-     * @return The revision.
+     * @return The date.
      */
-    public long getRevision() {
-        return revision;
+    public Calendar getDate() {
+        return date;
     }
 
     /**
@@ -91,17 +91,17 @@ public class VcsLogEntry {
 
     /**
      *
-     * @return The date.
+     * @return The path.
      */
-    public Calendar getDate() {
-        return date;
+    public String getPath() {
+        return path;
     }
 
     /**
      *
-     * @return The path.
+     * @return The revision.
      */
-    public String getPath() {
-        return path;
+    public long getRevision() {
+        return revision;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsRevert.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsRevert.java
index 9f9b803..747b6f5 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsRevert.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsRevert.java
@@ -30,12 +30,6 @@ public interface VcsRevert extends FileOperation {
 
     /**
      *
-     * @param recursive true if children should be processed.
-     */
-    void setRecursive(boolean recursive);
-
-    /**
-     *
      * @param listener The Listener to add.
      */
     void addModifyListener(VcsModifyListener listener);
@@ -45,4 +39,10 @@ public interface VcsRevert extends FileOperation {
      * @param listener The Listener to remove.
      */
     void removeModifyListener(VcsModifyListener listener);
+
+    /**
+     *
+     * @param recursive true if children should be processed.
+     */
+    void setRecursive(boolean recursive);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsUpdate.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsUpdate.java
index fa4fa30..716cc47 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsUpdate.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/operations/vcs/VcsUpdate.java
@@ -26,25 +26,25 @@ public interface VcsUpdate extends FileOperation {
 
     /**
      *
-     * @param revision The revision number.
+     * @param listener The UpdateListener.
      */
-    void setRevision(long revision);
+    void addUpdateListener(VcsUpdateListener listener);
 
     /**
      *
-     * @param isRecursive true if recursive.
+     * @param listener The UpdateListener.
      */
-    void setRecursive(boolean isRecursive);
+    void removeUpdateListener(VcsUpdateListener listener);
 
     /**
      *
-     * @param listener The UpdateListener.
+     * @param isRecursive true if recursive.
      */
-    void addUpdateListener(VcsUpdateListener listener);
+    void setRecursive(boolean isRecursive);
 
     /**
      *
-     * @param listener The UpdateListener.
+     * @param revision The revision number.
      */
-    void removeUpdateListener(VcsUpdateListener listener);
+    void setRevision(long revision);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileName.java
index daafa83..5468b04 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileName.java
@@ -75,26 +75,53 @@ public abstract class AbstractFileName implements FileName {
         }
     }
 
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) {
+    /**
+     * Checks whether a path fits in a particular scope of another path.
+     *
+     * @param basePath An absolute, normalised path.
+     * @param path An absolute, normalised path.
+     * @param scope The NameScope.
+     * @return true if the path fits in the scope, false otherwise.
+     */
+    public static boolean checkName(final String basePath, final String path, final NameScope scope) {
+        if (scope == NameScope.FILE_SYSTEM) {
+            // All good
             return true;
         }
-        if (o == null || getClass() != o.getClass()) {
+
+        if (!path.startsWith(basePath)) {
             return false;
         }
 
-        final AbstractFileName that = (AbstractFileName) o;
+        int baseLen = basePath.length();
+        if (VFS.isUriStyle()) {
+            // strip the trailing "/"
+            baseLen--;
+        }
 
-        return getKey().equals(that.getKey());
-    }
+        if (scope == NameScope.CHILD) {
+            return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR)
+                    && path.indexOf(SEPARATOR_CHAR, baseLen + 1) == -1;
+        }
+        if (scope == NameScope.DESCENDENT) {
+            return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR);
+        }
+        if (scope == NameScope.DESCENDENT_OR_SELF) {
+            return baseLen <= 1 || path.length() <= baseLen || path.charAt(baseLen) == SEPARATOR_CHAR;
+        }
+        throw new IllegalArgumentException();
 
-    @Override
-    public int hashCode() {
-        return getKey().hashCode();
     }
 
     /**
+     * Builds the root URI for this file name. Note that the root URI must not end with a separator character.
+     *
+     * @param buffer A StringBuilder to use to construct the URI.
+     * @param addPassword true if the password should be added, false otherwise.
+     */
+    protected abstract void appendRootUri(StringBuilder buffer, boolean addPassword);
+
+    /**
      * Implement Comparable.
      *
      * @param obj another abstract file name
@@ -107,16 +134,6 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * Returns the URI of the file.
-     *
-     * @return the FileName as a URI.
-     */
-    @Override
-    public String toString() {
-        return getURI();
-    }
-
-    /**
      * Factory method for creating name instances.
      *
      * @param absolutePath The absolute path.
@@ -125,13 +142,30 @@ public abstract class AbstractFileName implements FileName {
      */
     public abstract FileName createName(String absolutePath, FileType fileType);
 
-    /**
-     * Builds the root URI for this file name. Note that the root URI must not end with a separator character.
-     *
-     * @param buffer A StringBuilder to use to construct the URI.
-     * @param addPassword true if the password should be added, false otherwise.
-     */
-    protected abstract void appendRootUri(StringBuilder buffer, boolean addPassword);
+    protected String createURI() {
+        return createURI(false, true);
+    }
+
+    private String createURI(final boolean useAbsolutePath, final boolean usePassword) {
+        final StringBuilder buffer = new StringBuilder();
+        appendRootUri(buffer, usePassword);
+        buffer.append(handleURISpecialCharacters(useAbsolutePath ? absPath : getPath()));
+        return buffer.toString();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final AbstractFileName that = (AbstractFileName) o;
+
+        return getKey().equals(that.getKey());
+    }
 
     /**
      * Returns the base name of the file.
@@ -153,35 +187,68 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * Returns the absolute path of the file, relative to the root of the file system that the file belongs to.
+     * Returns the depth of this file name, within its file system.
      *
-     * @return The path String.
+     * @return The depth of the file name.
      */
     @Override
-    public String getPath() {
-        if (VFS.isUriStyle()) {
-            return absPath + getUriTrailer();
+    public int getDepth() {
+        final int len = getPath().length();
+        if (len == 0 || len == 1 && getPath().charAt(0) == SEPARATOR_CHAR) {
+            return 0;
         }
-        return absPath;
+        int depth = 1;
+        for (int pos = 0; pos > -1 && pos < len; depth++) {
+            pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
+        }
+        return depth;
     }
 
-    protected String getUriTrailer() {
-        return getType().hasChildren() ? "/" : "";
+    /**
+     * Returns the extension of this file name.
+     *
+     * @return The file extension.
+     */
+    @Override
+    public String getExtension() {
+        if (extension == null) {
+            getBaseName();
+            final int pos = baseName.lastIndexOf('.');
+            // if ((pos == -1) || (pos == baseName.length() - 1))
+            // imario@ops.co.at: Review of patch from adagoubard@chello.nl
+            // do not treat file names like
+            // .bashrc c:\windows\.java c:\windows\.javaws c:\windows\.jedit c:\windows\.appletviewer
+            // as extension
+            if (pos < 1 || pos == baseName.length() - 1) {
+                // No extension
+                extension = "";
+            } else {
+                extension = baseName.substring(pos + 1).intern();
+            }
+        }
+        return extension;
     }
 
     /**
-     * Returns the decoded path.
+     * Returns the URI without a password.
      *
-     * @return The decoded path String.
-     * @throws FileSystemException If an error occurs.
+     * @return Returns the URI without a password.
      */
     @Override
-    public String getPathDecoded() throws FileSystemException {
-        if (decodedAbsPath == null) {
-            decodedAbsPath = UriParser.decode(getPath());
-        }
+    public String getFriendlyURI() {
+        return createURI(false, false);
+    }
 
-        return decodedAbsPath;
+    /**
+     * Create a path that does not use the FileType since that field is not immutable.
+     *
+     * @return The key.
+     */
+    private String getKey() {
+        if (key == null) {
+            key = getURI();
+        }
+        return key;
     }
 
     /**
@@ -207,91 +274,31 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * find the root of the file system.
-     *
-     * @return The root FileName.
-     */
-    @Override
-    public FileName getRoot() {
-        FileName root = this;
-        while (root.getParent() != null) {
-            root = root.getParent();
-        }
-
-        return root;
-    }
-
-    /**
-     * Returns the URI scheme of this file.
-     *
-     * @return The protocol used to access the file.
-     */
-    @Override
-    public String getScheme() {
-        return scheme;
-    }
-
-    /**
-     * Returns the absolute URI of the file.
+     * Returns the absolute path of the file, relative to the root of the file system that the file belongs to.
      *
-     * @return The absolute URI of the file.
+     * @return The path String.
      */
     @Override
-    public String getURI() {
-        if (uriString == null) {
-            uriString = createURI();
-        }
-        return uriString;
-    }
-
-    protected String createURI() {
-        return createURI(false, true);
-    }
-
-    /**
-     * Create a path that does not use the FileType since that field is not immutable.
-     *
-     * @return The key.
-     */
-    private String getKey() {
-        if (key == null) {
-            key = getURI();
+    public String getPath() {
+        if (VFS.isUriStyle()) {
+            return absPath + getUriTrailer();
         }
-        return key;
+        return absPath;
     }
 
     /**
-     * Returns the URI without a password.
+     * Returns the decoded path.
      *
-     * @return Returns the URI without a password.
+     * @return The decoded path String.
+     * @throws FileSystemException If an error occurs.
      */
     @Override
-    public String getFriendlyURI() {
-        return createURI(false, false);
-    }
-
-    private String createURI(final boolean useAbsolutePath, final boolean usePassword) {
-        final StringBuilder buffer = new StringBuilder();
-        appendRootUri(buffer, usePassword);
-        buffer.append(handleURISpecialCharacters(useAbsolutePath ? absPath : getPath()));
-        return buffer.toString();
-    }
-
-    private String handleURISpecialCharacters(String uri) {
-        if (!StringUtils.isEmpty(uri)) {
-            try {
-                // VFS-325: Handle URI special characters in file name
-                // Decode the base URI and re-encode with URI special characters
-                uri = UriParser.decode(uri);
-
-                return UriParser.encode(uri, RESERVED_URI_CHARS);
-            } catch (final FileSystemException e) {
-                // Default to base URI value?
-                return uri;
-            }
+    public String getPathDecoded() throws FileSystemException {
+        if (decodedAbsPath == null) {
+            decodedAbsPath = UriParser.decode(getPath());
         }
 
-        return uri;
+        return decodedAbsPath;
     }
 
     /**
@@ -353,6 +360,21 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
+     * find the root of the file system.
+     *
+     * @return The root FileName.
+     */
+    @Override
+    public FileName getRoot() {
+        FileName root = this;
+        while (root.getParent() != null) {
+            root = root.getParent();
+        }
+
+        return root;
+    }
+
+    /**
      * Returns the root URI of the file system this file belongs to.
      *
      * @return The URI of the root.
@@ -369,46 +391,69 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * Returns the depth of this file name, within its file system.
+     * Returns the URI scheme of this file.
      *
-     * @return The depth of the file name.
+     * @return The protocol used to access the file.
      */
     @Override
-    public int getDepth() {
-        final int len = getPath().length();
-        if (len == 0 || len == 1 && getPath().charAt(0) == SEPARATOR_CHAR) {
-            return 0;
-        }
-        int depth = 1;
-        for (int pos = 0; pos > -1 && pos < len; depth++) {
-            pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
-        }
-        return depth;
+    public String getScheme() {
+        return scheme;
     }
 
     /**
-     * Returns the extension of this file name.
+     * Returns the requested or current type of this name.
+     * <p>
+     * The "requested" type is the one determined during resolving the name. n this case the name is a
+     * {@link FileType#FOLDER} if it ends with an "/" else it will be a {@link FileType#FILE}.
+     * </p>
+     * <p>
+     * Once attached it will be changed to reflect the real type of this resource.
+     * </p>
      *
-     * @return The file extension.
+     * @return {@link FileType#FOLDER} or {@link FileType#FILE}
      */
     @Override
-    public String getExtension() {
-        if (extension == null) {
-            getBaseName();
-            final int pos = baseName.lastIndexOf('.');
-            // if ((pos == -1) || (pos == baseName.length() - 1))
-            // imario@ops.co.at: Review of patch from adagoubard@chello.nl
-            // do not treat file names like
-            // .bashrc c:\windows\.java c:\windows\.javaws c:\windows\.jedit c:\windows\.appletviewer
-            // as extension
-            if (pos < 1 || pos == baseName.length() - 1) {
-                // No extension
-                extension = "";
-            } else {
-                extension = baseName.substring(pos + 1).intern();
+    public FileType getType() {
+        return type;
+    }
+
+    /**
+     * Returns the absolute URI of the file.
+     *
+     * @return The absolute URI of the file.
+     */
+    @Override
+    public String getURI() {
+        if (uriString == null) {
+            uriString = createURI();
+        }
+        return uriString;
+    }
+
+    protected String getUriTrailer() {
+        return getType().hasChildren() ? "/" : "";
+    }
+
+    private String handleURISpecialCharacters(String uri) {
+        if (!StringUtils.isEmpty(uri)) {
+            try {
+                // VFS-325: Handle URI special characters in file name
+                // Decode the base URI and re-encode with URI special characters
+                uri = UriParser.decode(uri);
+
+                return UriParser.encode(uri, RESERVED_URI_CHARS);
+            } catch (final FileSystemException e) {
+                // Default to base URI value?
+                return uri;
             }
         }
-        return extension;
+
+        return uri;
+    }
+
+    @Override
+    public int hashCode() {
+        return getKey().hashCode();
     }
 
     /**
@@ -466,23 +511,6 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * Returns the requested or current type of this name.
-     * <p>
-     * The "requested" type is the one determined during resolving the name. n this case the name is a
-     * {@link FileType#FOLDER} if it ends with an "/" else it will be a {@link FileType#FILE}.
-     * </p>
-     * <p>
-     * Once attached it will be changed to reflect the real type of this resource.
-     * </p>
-     *
-     * @return {@link FileType#FOLDER} or {@link FileType#FILE}
-     */
-    @Override
-    public FileType getType() {
-        return type;
-    }
-
-    /**
      * Sets the type of this file e.g. when it will be attached.
      *
      * @param type {@link FileType#FOLDER} or {@link FileType#FILE}
@@ -497,40 +525,12 @@ public abstract class AbstractFileName implements FileName {
     }
 
     /**
-     * Checks whether a path fits in a particular scope of another path.
+     * Returns the URI of the file.
      *
-     * @param basePath An absolute, normalised path.
-     * @param path An absolute, normalised path.
-     * @param scope The NameScope.
-     * @return true if the path fits in the scope, false otherwise.
+     * @return the FileName as a URI.
      */
-    public static boolean checkName(final String basePath, final String path, final NameScope scope) {
-        if (scope == NameScope.FILE_SYSTEM) {
-            // All good
-            return true;
-        }
-
-        if (!path.startsWith(basePath)) {
-            return false;
-        }
-
-        int baseLen = basePath.length();
-        if (VFS.isUriStyle()) {
-            // strip the trailing "/"
-            baseLen--;
-        }
-
-        if (scope == NameScope.CHILD) {
-            return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR)
-                    && path.indexOf(SEPARATOR_CHAR, baseLen + 1) == -1;
-        }
-        if (scope == NameScope.DESCENDENT) {
-            return path.length() != baseLen && (baseLen <= 1 || path.charAt(baseLen) == SEPARATOR_CHAR);
-        }
-        if (scope == NameScope.DESCENDENT_OR_SELF) {
-            return baseLen <= 1 || path.length() <= baseLen || path.charAt(baseLen) == SEPARATOR_CHAR;
-        }
-        throw new IllegalArgumentException();
-
+    @Override
+    public String toString() {
+        return getURI();
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileProvider.java
index a13a0da..3892ce1 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileProvider.java
@@ -52,12 +52,26 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
         parser = GenericFileNameParser.getInstance();
     }
 
-    protected FileNameParser getFileNameParser() {
-        return parser;
-    }
+    /**
+     * Adds a file system to those cached by this provider.
+     * <p>
+     * The file system may implement {@link VfsComponent}, in which case it is initialized.
+     * </p>
+     *
+     * @param key The root file of the file system, part of the cache key.
+     * @param fs the file system to add.
+     * @throws FileSystemException if any error occurs.
+     */
+    protected void addFileSystem(final Comparable<?> key, final FileSystem fs) throws FileSystemException {
+        // Add to the container and initialize
+        addComponent(fs);
 
-    protected void setFileNameParser(final FileNameParser parser) {
-        this.parser = parser;
+        final FileSystemKey treeKey = new FileSystemKey(key, fs.getFileSystemOptions());
+        ((AbstractFileSystem) fs).setCacheKey(treeKey);
+
+        synchronized (fileSystemMap) {
+            fileSystemMap.put(treeKey, fs);
+        }
     }
 
     /**
@@ -72,6 +86,25 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
     }
 
     /**
+     * Closes the FileSystem.
+     *
+     * @param fileSystem The FileSystem to close.
+     */
+    public void closeFileSystem(final FileSystem fileSystem) {
+        final AbstractFileSystem fs = (AbstractFileSystem) fileSystem;
+
+        final FileSystemKey key = fs.getCacheKey();
+        if (key != null) {
+            synchronized (fileSystemMap) {
+                fileSystemMap.remove(key);
+            }
+        }
+
+        removeComponent(fs);
+        fs.close();
+    }
+
+    /**
      * Creates a layered file system. This method throws a 'not supported' exception.
      *
      * @param scheme The protocol to use to access the file.
@@ -88,28 +121,6 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
     }
 
     /**
-     * Adds a file system to those cached by this provider.
-     * <p>
-     * The file system may implement {@link VfsComponent}, in which case it is initialized.
-     * </p>
-     *
-     * @param key The root file of the file system, part of the cache key.
-     * @param fs the file system to add.
-     * @throws FileSystemException if any error occurs.
-     */
-    protected void addFileSystem(final Comparable<?> key, final FileSystem fs) throws FileSystemException {
-        // Add to the container and initialize
-        addComponent(fs);
-
-        final FileSystemKey treeKey = new FileSystemKey(key, fs.getFileSystemOptions());
-        ((AbstractFileSystem) fs).setCacheKey(treeKey);
-
-        synchronized (fileSystemMap) {
-            fileSystemMap.put(treeKey, fs);
-        }
-    }
-
-    /**
      * Locates a cached file system.
      *
      * @param key The root file of the file system, part of the cache key.
@@ -123,16 +134,6 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
     }
 
     /**
-     * Gets the FileSystemConfigBuidler.
-     *
-     * @return the FileSystemConfigBuilder.
-     */
-    @Override
-    public FileSystemConfigBuilder getConfigBuilder() {
-        return null;
-    }
-
-    /**
      * Frees unused resources.
      */
     public void freeUnusedResources() {
@@ -148,22 +149,17 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
     }
 
     /**
-     * Closes the FileSystem.
+     * Gets the FileSystemConfigBuidler.
      *
-     * @param fileSystem The FileSystem to close.
+     * @return the FileSystemConfigBuilder.
      */
-    public void closeFileSystem(final FileSystem fileSystem) {
-        final AbstractFileSystem fs = (AbstractFileSystem) fileSystem;
-
-        final FileSystemKey key = fs.getCacheKey();
-        if (key != null) {
-            synchronized (fileSystemMap) {
-                fileSystemMap.remove(key);
-            }
-        }
+    @Override
+    public FileSystemConfigBuilder getConfigBuilder() {
+        return null;
+    }
 
-        removeComponent(fs);
-        fs.close();
+    protected FileNameParser getFileNameParser() {
+        return parser;
     }
 
     /**
@@ -182,4 +178,8 @@ public abstract class AbstractFileProvider extends AbstractVfsContainer implemen
 
         throw new FileSystemException("vfs.provider/filename-parser-missing.error");
     }
+
+    protected void setFileNameParser(final FileNameParser parser) {
+        this.parser = parser;
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileSystem.java
index 6262dac..2521630 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractFileSystem.java
@@ -55,11 +55,6 @@ import org.apache.commons.vfs2.util.Messages;
  */
 public abstract class AbstractFileSystem extends AbstractVfsComponent implements FileSystem {
 
-    /** Only provided for Serializable subclasses. */
-    AbstractFileSystem() {
-        this(null, null, null);
-    }
-
     private static final FileListener[] EMPTY_FILE_LISTENER_ARRAY = {};
 
     private static final Log LOG = LogFactory.getLog(AbstractFileSystem.class);
@@ -101,6 +96,11 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
      */
     private final AtomicInteger openStreams = new AtomicInteger(0);
 
+    /** Only provided for Serializable subclasses. */
+    AbstractFileSystem() {
+        this(null, null, null);
+    }
+
     /**
      * Constructs a new instance.
      *
@@ -121,13 +121,36 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
     }
 
     /**
-     * Initializes this component.
+     * Adds the capabilities of this file system.
+     *
+     * @param caps collections of Capabilities, can be immutable.
+     */
+    protected abstract void addCapabilities(Collection<Capability> caps);
+
+    /**
+     * Adds a junction to this file system.
      *
+     * @param junctionPoint The junction point.
+     * @param targetFile The target to add.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void init() throws FileSystemException {
-        addCapabilities(capabilities);
+    public void addJunction(final String junctionPoint, final FileObject targetFile) throws FileSystemException {
+        throw new FileSystemException("vfs.provider/junctions-not-supported.error", rootName);
+    }
+
+    /**
+     * Adds a listener on a file in this file system.
+     *
+     * @param file The FileObject to be monitored.
+     * @param listener The FileListener
+     */
+    @Override
+    public void addListener(final FileObject file, final FileListener listener) {
+        synchronized (listenerMap) {
+            final ArrayList<FileListener> listeners = listenerMap.computeIfAbsent(file.getName(), k -> new ArrayList<>());
+            listeners.add(listener);
+        }
     }
 
     /**
@@ -148,13 +171,6 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
     }
 
     /**
-     * Closes the underlying link used to access the files.
-     */
-    protected void doCloseCommunicationLink() {
-        // default is noop.
-    }
-
-    /**
      * Creates a file object.
      * <p>
      * This method is called only if the requested file is not cached.
@@ -166,50 +182,125 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
      */
     protected abstract FileObject createFile(AbstractFileName name) throws Exception;
 
+    protected FileObject decorateFileObject(FileObject file) throws FileSystemException {
+        if (getFileSystemManager().getCacheStrategy().equals(CacheStrategy.ON_CALL)) {
+            file = new OnCallRefreshFileObject(file);
+        }
+
+        if (getFileSystemManager().getFileObjectDecoratorConst() != null) {
+            try {
+                file = (FileObject) getFileSystemManager().getFileObjectDecoratorConst().newInstance(file);
+            } catch (final InstantiationException | IllegalAccessException | InvocationTargetException e) {
+                throw new FileSystemException("vfs.impl/invalid-decorator.error",
+                        getFileSystemManager().getFileObjectDecorator().getName(), e);
+            }
+        }
+
+        return file;
+    }
+
     /**
-     * Adds the capabilities of this file system.
+     * Closes the underlying link used to access the files.
+     */
+    protected void doCloseCommunicationLink() {
+        // default is noop.
+    }
+
+    /**
+     * Creates a temporary local copy of a file and its descendants.
      *
-     * @param caps collections of Capabilities, can be immutable.
+     * @param file the start of the tree.
+     * @param selector selection what to do with childs.
+     * @return replicated root file.
+     * @throws Exception any Exception is wrapped as FileSystemException.
      */
-    protected abstract void addCapabilities(Collection<Capability> caps);
+    protected File doReplicateFile(final FileObject file, final FileSelector selector) throws Exception {
+        return getContext().getReplicator().replicateFile(file, selector);
+    }
+
+    void fileObjectDestroyed(final FileObject fileObject) {
+        useCount.decrementAndGet();
+    }
+
+    void fileObjectHanded(final FileObject fileObject) {
+        useCount.incrementAndGet();
+    }
 
     /**
-     * Returns the name of the root of this file system.
+     * Fires an event.
+     */
+    private void fireEvent(final AbstractFileChangeEvent event) {
+        FileListener[] fileListeners = null;
+        final FileObject fileObject = event.getFileObject();
+
+        synchronized (listenerMap) {
+            final ArrayList<?> listeners = listenerMap.get(fileObject.getName());
+            if (listeners != null) {
+                fileListeners = listeners.toArray(EMPTY_FILE_LISTENER_ARRAY);
+            }
+        }
+
+        if (fileListeners != null) {
+            for (final FileListener fileListener : fileListeners) {
+                try {
+                    event.notify(fileListener);
+                } catch (final Exception e) {
+                    final String message = Messages.getString("vfs.provider/notify-listener.warn", fileObject);
+                    // getLogger().warn(message, e);
+                    VfsLog.warn(getLogger(), LOG, message, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Fires a file changed event.
+     * <p>
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
+     * </p>
      *
-     * @return the root FileName.
+     * @param file The FileObject that changed.
      */
-    @Override
-    public FileName getRootName() {
-        return rootName;
+    public void fireFileChanged(final FileObject file) {
+        fireEvent(new ChangedEvent(file));
     }
 
     /**
-     * Returns the root URI specified for this file System.
+     * Fires a file create event.
      *
-     * @return The root URI used in this file system.
-     * @since 2.0
+     * @param file The FileObject that was created.
      */
-    @Override
-    public String getRootURI() {
-        return rootURI;
+    public void fireFileCreated(final FileObject file) {
+        fireEvent(new CreateEvent(file));
     }
 
     /**
-     * Adds a file object to the cache.
+     * Fires a file delete event.
      *
-     * @param file the file to add.
+     * @param file The FileObject that was deleted.
      */
-    protected void putFileToCache(final FileObject file) {
-        getFilesCache().putFile(file);
+    public void fireFileDeleted(final FileObject file) {
+        fireEvent(new DeleteEvent(file));
     }
 
-    private FilesCache getFilesCache() {
-        final FilesCache filesCache = getContext().getFileSystemManager().getFilesCache();
-        if (filesCache == null) {
-            throw new RuntimeException(Messages.getString("vfs.provider/files-cache-missing.error"));
-        }
+    void freeResources() {
+        // default is noop.
+    }
 
-        return filesCache;
+    /**
+     * Retrieves the attribute with the specified name. The default implementation simply throws an exception.
+     *
+     * @param attrName The name of the attribute.
+     * @return the Object associated with the attribute or null if no object is.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public Object getAttribute(final String attrName) throws FileSystemException {
+        throw new FileSystemException("vfs.provider/get-attribute-not-supported.error");
+    }
+
+    FileSystemKey getCacheKey() {
+        return this.cacheKey;
     }
 
     /**
@@ -222,48 +313,43 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
         return getFilesCache().getFile(this, name);
     }
 
-    /**
-     * Removes a cached file.
-     *
-     * @param name The file name to remove.
-     */
-    protected void removeFileFromCache(final FileName name) {
-        getFilesCache().removeFile(this, name);
+    private FilesCache getFilesCache() {
+        final FilesCache filesCache = getContext().getFileSystemManager().getFilesCache();
+        if (filesCache == null) {
+            throw new RuntimeException(Messages.getString("vfs.provider/files-cache-missing.error"));
+        }
+
+        return filesCache;
     }
 
     /**
-     * Determines if this file system has a particular capability.
+     * Returns the FileSystemManager used to instantiate this file system.
      *
-     * @param capability the Capability to check for.
-     * @return true if the FileSystem has the Capability, false otherwise.
+     * @return the FileSystemManager.
      */
     @Override
-    public boolean hasCapability(final Capability capability) {
-        return capabilities.contains(capability);
+    public FileSystemManager getFileSystemManager() {
+        return getContext().getFileSystemManager();
     }
 
     /**
-     * Retrieves the attribute with the specified name. The default implementation simply throws an exception.
+     * Returns the FileSystemOptions used to instantiate this file system.
      *
-     * @param attrName The name of the attribute.
-     * @return the Object associated with the attribute or null if no object is.
-     * @throws FileSystemException if an error occurs.
+     * @return the FileSystemOptions.
      */
     @Override
-    public Object getAttribute(final String attrName) throws FileSystemException {
-        throw new FileSystemException("vfs.provider/get-attribute-not-supported.error");
+    public FileSystemOptions getFileSystemOptions() {
+        return fileSystemOptions;
     }
 
     /**
-     * Sets the attribute with the specified name. The default implementation simply throws an exception.
+     * Returns the accuracy of the last modification time.
      *
-     * @param attrName the attribute name.
-     * @param value The object to associate with the attribute.
-     * @throws FileSystemException if an error occurs.
+     * @return ms 0 perfectly accurate, {@literal >0} might be off by this value e.g. sftp 1000ms
      */
     @Override
-    public void setAttribute(final String attrName, final Object value) throws FileSystemException {
-        throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
+    public double getLastModTimeAccuracy() {
+        return 0;
     }
 
     /**
@@ -289,159 +375,88 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
     }
 
     /**
-     * Finds a file in this file system.
+     * Returns the name of the root of this file system.
      *
-     * @param nameStr The name of the file to resolve.
-     * @return The located FileObject or null if none could be located.
-     * @throws FileSystemException if an error occurs.
+     * @return the root FileName.
      */
     @Override
-    public FileObject resolveFile(final String nameStr) throws FileSystemException {
-        // Resolve the name, and create the file
-        return resolveFile(getFileSystemManager().resolveName(rootName, nameStr));
+    public FileName getRootName() {
+        return rootName;
     }
 
     /**
-     * Finds a file in this file system.
+     * Returns the root URI specified for this file System.
      *
-     * @param name The name of the file to locate.
-     * @return The located FileObject or null if none could be located.
-     * @throws FileSystemException if an error occurs.
+     * @return The root URI used in this file system.
+     * @since 2.0
      */
     @Override
-    public FileObject resolveFile(final FileName name) throws FileSystemException {
-        return resolveFile(name, true);
+    public String getRootURI() {
+        return rootURI;
     }
 
-    private synchronized FileObject resolveFile(final FileName name, final boolean useCache)
-            throws FileSystemException {
-        if (!rootName.getRootURI().equals(name.getRootURI())) {
-            throw new FileSystemException("vfs.provider/mismatched-fs-for-name.error", name, rootName,
-                    name.getRootURI());
-        }
-
-        // imario@apache.org ==> use getFileFromCache
-        FileObject file;
-        if (useCache) {
-            file = getFileFromCache(name);
-        } else {
-            file = null;
-        }
-
-        if (file == null) {
-            try {
-                file = createFile((AbstractFileName) name);
-            } catch (final Exception e) {
-                throw new FileSystemException("vfs.provider/resolve-file.error", name, e);
-            }
-
-            file = decorateFileObject(file);
-
-            // imario@apache.org ==> use putFileToCache
-            if (useCache) {
-                putFileToCache(file);
-            }
-        }
-
-        /*
-          resync the file information if requested
-         */
-        if (getFileSystemManager().getCacheStrategy().equals(CacheStrategy.ON_RESOLVE)) {
-            file.refresh();
-        }
-        return file;
-    }
-
-    protected FileObject decorateFileObject(FileObject file) throws FileSystemException {
-        if (getFileSystemManager().getCacheStrategy().equals(CacheStrategy.ON_CALL)) {
-            file = new OnCallRefreshFileObject(file);
-        }
-
-        if (getFileSystemManager().getFileObjectDecoratorConst() != null) {
-            try {
-                file = (FileObject) getFileSystemManager().getFileObjectDecoratorConst().newInstance(file);
-            } catch (final InstantiationException | IllegalAccessException | InvocationTargetException e) {
-                throw new FileSystemException("vfs.impl/invalid-decorator.error",
-                        getFileSystemManager().getFileObjectDecorator().getName(), e);
-            }
-        }
-
-        return file;
-    }
+    /**
+     * Determines if this file system has a particular capability.
+     *
+     * @param capability the Capability to check for.
+     * @return true if the FileSystem has the Capability, false otherwise.
+     */
+    @Override
+    public boolean hasCapability(final Capability capability) {
+        return capabilities.contains(capability);
+    }
 
     /**
-     * Creates a temporary local copy of a file and its descendants.
+     * Initializes this component.
      *
-     * @param file The FileObject to replicate.
-     * @param selector The FileSelector.
-     * @return The replicated File.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public File replicateFile(final FileObject file, final FileSelector selector) throws FileSystemException {
-        if (!FileObjectUtils.exists(file)) {
-            throw new FileSystemException("vfs.provider/replicate-missing-file.error", file.getName());
-        }
-
-        try {
-            return doReplicateFile(file, selector);
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.provider/replicate-file.error", file.getName(), e);
-        }
+    public void init() throws FileSystemException {
+        addCapabilities(capabilities);
     }
 
     /**
-     * Returns the FileSystemOptions used to instantiate this file system.
+     * Checks if this file system has open streams.
      *
-     * @return the FileSystemOptions.
+     * @return true if the FileSystem has open streams.
      */
-    @Override
-    public FileSystemOptions getFileSystemOptions() {
-        return fileSystemOptions;
+    public boolean isOpen() {
+        return openStreams.get() > 0;
     }
 
     /**
-     * Returns the FileSystemManager used to instantiate this file system.
+     * Returns true if no file is using this FileSystem.
      *
-     * @return the FileSystemManager.
+     * @return true if no file is using this FileSystem.
      */
-    @Override
-    public FileSystemManager getFileSystemManager() {
-        return getContext().getFileSystemManager();
+    public boolean isReleaseable() {
+        return useCount.get() < 1;
     }
 
     /**
-     * Returns the accuracy of the last modification time.
-     *
-     * @return ms 0 perfectly accurate, {@literal >0} might be off by this value e.g. sftp 1000ms
+     * Called after all file-objects closed their streams.
      */
-    @Override
-    public double getLastModTimeAccuracy() {
-        return 0;
+    protected void notifyAllStreamsClosed() {
+        // default is noop.
     }
 
     /**
-     * Creates a temporary local copy of a file and its descendants.
+     * Adds a file object to the cache.
      *
-     * @param file the start of the tree.
-     * @param selector selection what to do with childs.
-     * @return replicated root file.
-     * @throws Exception any Exception is wrapped as FileSystemException.
+     * @param file the file to add.
      */
-    protected File doReplicateFile(final FileObject file, final FileSelector selector) throws Exception {
-        return getContext().getReplicator().replicateFile(file, selector);
+    protected void putFileToCache(final FileObject file) {
+        getFilesCache().putFile(file);
     }
 
     /**
-     * Adds a junction to this file system.
+     * Removes a cached file.
      *
-     * @param junctionPoint The junction point.
-     * @param targetFile The target to add.
-     * @throws FileSystemException if an error occurs.
+     * @param name The file name to remove.
      */
-    @Override
-    public void addJunction(final String junctionPoint, final FileObject targetFile) throws FileSystemException {
-        throw new FileSystemException("vfs.provider/junctions-not-supported.error", rootName);
+    protected void removeFileFromCache(final FileName name) {
+        getFilesCache().removeFile(this, name);
     }
 
     /**
@@ -456,20 +471,6 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
     }
 
     /**
-     * Adds a listener on a file in this file system.
-     *
-     * @param file The FileObject to be monitored.
-     * @param listener The FileListener
-     */
-    @Override
-    public void addListener(final FileObject file, final FileListener listener) {
-        synchronized (listenerMap) {
-            final ArrayList<FileListener> listeners = listenerMap.computeIfAbsent(file.getName(), k -> new ArrayList<>());
-            listeners.add(listener);
-        }
-    }
-
-    /**
      * Removes a listener from a file in this file system.
      *
      * @param file The FileObject to be monitored.
@@ -489,114 +490,113 @@ public abstract class AbstractFileSystem extends AbstractVfsComponent implements
     }
 
     /**
-     * Fires a file create event.
+     * Creates a temporary local copy of a file and its descendants.
      *
-     * @param file The FileObject that was created.
+     * @param file The FileObject to replicate.
+     * @param selector The FileSelector.
+     * @return The replicated File.
+     * @throws FileSystemException if an error occurs.
      */
-    public void fireFileCreated(final FileObject file) {
-        fireEvent(new CreateEvent(file));
-    }
+    @Override
+    public File replicateFile(final FileObject file, final FileSelector selector) throws FileSystemException {
+        if (!FileObjectUtils.exists(file)) {
+            throw new FileSystemException("vfs.provider/replicate-missing-file.error", file.getName());
+        }
 
-    /**
-     * Fires a file delete event.
-     *
-     * @param file The FileObject that was deleted.
-     */
-    public void fireFileDeleted(final FileObject file) {
-        fireEvent(new DeleteEvent(file));
+        try {
+            return doReplicateFile(file, selector);
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider/replicate-file.error", file.getName(), e);
+        }
     }
 
     /**
-     * Fires a file changed event.
-     * <p>
-     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
-     * </p>
+     * Finds a file in this file system.
      *
-     * @param file The FileObject that changed.
+     * @param name The name of the file to locate.
+     * @return The located FileObject or null if none could be located.
+     * @throws FileSystemException if an error occurs.
      */
-    public void fireFileChanged(final FileObject file) {
-        fireEvent(new ChangedEvent(file));
+    @Override
+    public FileObject resolveFile(final FileName name) throws FileSystemException {
+        return resolveFile(name, true);
     }
 
-    /**
-     * Returns true if no file is using this FileSystem.
-     *
-     * @return true if no file is using this FileSystem.
-     */
-    public boolean isReleaseable() {
-        return useCount.get() < 1;
-    }
+    private synchronized FileObject resolveFile(final FileName name, final boolean useCache)
+            throws FileSystemException {
+        if (!rootName.getRootURI().equals(name.getRootURI())) {
+            throw new FileSystemException("vfs.provider/mismatched-fs-for-name.error", name, rootName,
+                    name.getRootURI());
+        }
 
-    void freeResources() {
-        // default is noop.
-    }
+        // imario@apache.org ==> use getFileFromCache
+        FileObject file;
+        if (useCache) {
+            file = getFileFromCache(name);
+        } else {
+            file = null;
+        }
 
-    /**
-     * Fires an event.
-     */
-    private void fireEvent(final AbstractFileChangeEvent event) {
-        FileListener[] fileListeners = null;
-        final FileObject fileObject = event.getFileObject();
+        if (file == null) {
+            try {
+                file = createFile((AbstractFileName) name);
+            } catch (final Exception e) {
+                throw new FileSystemException("vfs.provider/resolve-file.error", name, e);
+            }
 
-        synchronized (listenerMap) {
-            final ArrayList<?> listeners = listenerMap.get(fileObject.getName());
-            if (listeners != null) {
-                fileListeners = listeners.toArray(EMPTY_FILE_LISTENER_ARRAY);
+            file = decorateFileObject(file);
+
+            // imario@apache.org ==> use putFileToCache
+            if (useCache) {
+                putFileToCache(file);
             }
         }
 
-        if (fileListeners != null) {
-            for (final FileListener fileListener : fileListeners) {
-                try {
-                    event.notify(fileListener);
-                } catch (final Exception e) {
-                    final String message = Messages.getString("vfs.provider/notify-listener.warn", fileObject);
-                    // getLogger().warn(message, e);
-                    VfsLog.warn(getLogger(), LOG, message, e);
-                }
-            }
+        /*
+          resync the file information if requested
+         */
+        if (getFileSystemManager().getCacheStrategy().equals(CacheStrategy.ON_RESOLVE)) {
+            file.refresh();
         }
+        return file;
     }
 
-    void fileObjectHanded(final FileObject fileObject) {
-        useCount.incrementAndGet();
+    /**
+     * Finds a file in this file system.
+     *
+     * @param nameStr The name of the file to resolve.
+     * @return The located FileObject or null if none could be located.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public FileObject resolveFile(final String nameStr) throws FileSystemException {
+        // Resolve the name, and create the file
+        return resolveFile(getFileSystemManager().resolveName(rootName, nameStr));
     }
 
-    void fileObjectDestroyed(final FileObject fileObject) {
-        useCount.decrementAndGet();
+    /**
+     * Sets the attribute with the specified name. The default implementation simply throws an exception.
+     *
+     * @param attrName the attribute name.
+     * @param value The object to associate with the attribute.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public void setAttribute(final String attrName, final Object value) throws FileSystemException {
+        throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
     }
 
     void setCacheKey(final FileSystemKey cacheKey) {
         this.cacheKey = cacheKey;
     }
 
-    FileSystemKey getCacheKey() {
-        return this.cacheKey;
-    }
-
-    void streamOpened() {
-        openStreams.incrementAndGet();
-    }
-
     void streamClosed() {
         if (openStreams.decrementAndGet() == 0) {
             notifyAllStreamsClosed();
         }
     }
 
-    /**
-     * Called after all file-objects closed their streams.
-     */
-    protected void notifyAllStreamsClosed() {
-        // default is noop.
-    }
-
-    /**
-     * Checks if this file system has open streams.
-     *
-     * @return true if the FileSystem has open streams.
-     */
-    public boolean isOpen() {
-        return openStreams.get() > 0;
+    void streamOpened() {
+        openStreams.incrementAndGet();
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractLayeredFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractLayeredFileProvider.java
index 591fb3c..5e09441 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractLayeredFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractLayeredFileProvider.java
@@ -35,34 +35,6 @@ public abstract class AbstractLayeredFileProvider extends AbstractFileProvider {
     }
 
     /**
-     * Locates a file object, by absolute URI.
-     *
-     * @param baseFile The base FileObject.
-     * @param uri The name of the file to locate.
-     * @param fileSystemOptions The FileSystemOptions.
-     * @return The FileObject if it is located, null otherwise.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public FileObject findFile(final FileObject baseFile, final String uri, final FileSystemOptions fileSystemOptions)
-            throws FileSystemException {
-        // Split the URI up into its parts
-        final LayeredFileName name = (LayeredFileName) parseUri(baseFile != null ? baseFile.getName() : null, uri);
-
-        // Make the URI canonical
-
-        // Resolve the outer file name
-        final FileName fileName = name.getOuterName();
-        final FileObject file = getContext().resolveFile(baseFile, fileName.getURI(), fileSystemOptions);
-
-        // Create the file system
-        final FileObject rootFile = createFileSystem(name.getScheme(), file, fileSystemOptions);
-
-        // Resolve the file
-        return rootFile.resolveFile(name.getPath());
-    }
-
-    /**
      * Creates a layered file system.
      *
      * @param scheme The protocol to use.
@@ -99,4 +71,32 @@ public abstract class AbstractLayeredFileProvider extends AbstractFileProvider {
      */
     protected abstract FileSystem doCreateFileSystem(String scheme, FileObject file, FileSystemOptions fileSystemOptions) throws FileSystemException;
 
+    /**
+     * Locates a file object, by absolute URI.
+     *
+     * @param baseFile The base FileObject.
+     * @param uri The name of the file to locate.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return The FileObject if it is located, null otherwise.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public FileObject findFile(final FileObject baseFile, final String uri, final FileSystemOptions fileSystemOptions)
+            throws FileSystemException {
+        // Split the URI up into its parts
+        final LayeredFileName name = (LayeredFileName) parseUri(baseFile != null ? baseFile.getName() : null, uri);
+
+        // Make the URI canonical
+
+        // Resolve the outer file name
+        final FileName fileName = name.getOuterName();
+        final FileObject file = getContext().resolveFile(baseFile, fileName.getURI(), fileSystemOptions);
+
+        // Create the file system
+        final FileObject rootFile = createFileSystem(name.getScheme(), file, fileSystemOptions);
+
+        // Resolve the file
+        return rootFile.resolveFile(name.getPath());
+    }
+
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractOriginatingFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractOriginatingFileProvider.java
index 58f125a..d6c0321 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractOriginatingFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractOriginatingFileProvider.java
@@ -35,28 +35,14 @@ public abstract class AbstractOriginatingFileProvider extends AbstractFileProvid
     }
 
     /**
-     * Locates a file object, by absolute URI.
+     * Creates a {@link FileSystem}. If the returned FileSystem implements {@link VfsComponent}, it will be initialized.
      *
-     * @param baseFileObject The base file object.
-     * @param uri The URI of the file to locate
+     * @param rootFileName The name of the root file of the file system to create.
      * @param fileSystemOptions The FileSystem options.
-     * @return The located FileObject
+     * @return The FileSystem.
      * @throws FileSystemException if an error occurs.
      */
-    @Override
-    public FileObject findFile(final FileObject baseFileObject, final String uri, final FileSystemOptions fileSystemOptions)
-            throws FileSystemException {
-        // Parse the URI
-        final FileName name;
-        try {
-            name = parseUri(baseFileObject != null ? baseFileObject.getName() : null, uri);
-        } catch (final FileSystemException exc) {
-            throw new FileSystemException("vfs.provider/invalid-absolute-uri.error", uri, exc);
-        }
-
-        // Locate the file
-        return findFile(name, fileSystemOptions);
-    }
+    protected abstract FileSystem doCreateFileSystem(FileName rootFileName, FileSystemOptions fileSystemOptions) throws FileSystemException;
 
     /**
      * Locates a file from its parsed URI.
@@ -79,6 +65,30 @@ public abstract class AbstractOriginatingFileProvider extends AbstractFileProvid
     }
 
     /**
+     * Locates a file object, by absolute URI.
+     *
+     * @param baseFileObject The base file object.
+     * @param uri The URI of the file to locate
+     * @param fileSystemOptions The FileSystem options.
+     * @return The located FileObject
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public FileObject findFile(final FileObject baseFileObject, final String uri, final FileSystemOptions fileSystemOptions)
+            throws FileSystemException {
+        // Parse the URI
+        final FileName name;
+        try {
+            name = parseUri(baseFileObject != null ? baseFileObject.getName() : null, uri);
+        } catch (final FileSystemException exc) {
+            throw new FileSystemException("vfs.provider/invalid-absolute-uri.error", uri, exc);
+        }
+
+        // Locate the file
+        return findFile(name, fileSystemOptions);
+    }
+
+    /**
      * Returns the FileSystem associated with the specified root.
      *
      * @param rootFileName The root path.
@@ -97,14 +107,4 @@ public abstract class AbstractOriginatingFileProvider extends AbstractFileProvid
         }
         return fs;
     }
-
-    /**
-     * Creates a {@link FileSystem}. If the returned FileSystem implements {@link VfsComponent}, it will be initialized.
-     *
-     * @param rootFileName The name of the root file of the file system to create.
-     * @param fileSystemOptions The FileSystem options.
-     * @return The FileSystem.
-     * @throws FileSystemException if an error occurs.
-     */
-    protected abstract FileSystem doCreateFileSystem(FileName rootFileName, FileSystemOptions fileSystemOptions) throws FileSystemException;
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractRandomAccessStreamContent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractRandomAccessStreamContent.java
index e8d7c3a..0928fc4 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractRandomAccessStreamContent.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractRandomAccessStreamContent.java
@@ -34,6 +34,16 @@ public abstract class AbstractRandomAccessStreamContent extends AbstractRandomAc
     protected abstract DataInputStream getDataInputStream() throws IOException;
 
     @Override
+    public InputStream getInputStream() throws IOException {
+        return getDataInputStream();
+    }
+
+    @Override
+    public boolean readBoolean() throws IOException {
+        return getDataInputStream().readBoolean();
+    }
+
+    @Override
     public byte readByte() throws IOException {
         return getDataInputStream().readByte();
     }
@@ -54,18 +64,18 @@ public abstract class AbstractRandomAccessStreamContent extends AbstractRandomAc
     }
 
     @Override
-    public int readInt() throws IOException {
-        return getDataInputStream().readInt();
+    public void readFully(final byte[] b) throws IOException {
+        getDataInputStream().readFully(b);
     }
 
     @Override
-    public int readUnsignedByte() throws IOException {
-        return getDataInputStream().readUnsignedByte();
+    public void readFully(final byte[] b, final int off, final int len) throws IOException {
+        getDataInputStream().readFully(b, off, len);
     }
 
     @Override
-    public int readUnsignedShort() throws IOException {
-        return getDataInputStream().readUnsignedShort();
+    public int readInt() throws IOException {
+        return getDataInputStream().readInt();
     }
 
     @Override
@@ -79,23 +89,13 @@ public abstract class AbstractRandomAccessStreamContent extends AbstractRandomAc
     }
 
     @Override
-    public boolean readBoolean() throws IOException {
-        return getDataInputStream().readBoolean();
-    }
-
-    @Override
-    public int skipBytes(final int n) throws IOException {
-        return getDataInputStream().skipBytes(n);
-    }
-
-    @Override
-    public void readFully(final byte[] b) throws IOException {
-        getDataInputStream().readFully(b);
+    public int readUnsignedByte() throws IOException {
+        return getDataInputStream().readUnsignedByte();
     }
 
     @Override
-    public void readFully(final byte[] b, final int off, final int len) throws IOException {
-        getDataInputStream().readFully(b, off, len);
+    public int readUnsignedShort() throws IOException {
+        return getDataInputStream().readUnsignedShort();
     }
 
     @Override
@@ -104,12 +104,12 @@ public abstract class AbstractRandomAccessStreamContent extends AbstractRandomAc
     }
 
     @Override
-    public InputStream getInputStream() throws IOException {
-        return getDataInputStream();
+    public void setLength(final long newLength) throws IOException {
+        throw new UnsupportedOperationException();
     }
 
     @Override
-    public void setLength(final long newLength) throws IOException {
-        throw new UnsupportedOperationException();
+    public int skipBytes(final int n) throws IOException {
+        return getDataInputStream().skipBytes(n);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsComponent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsComponent.java
index 39b0cc3..0b37dba 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsComponent.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsComponent.java
@@ -28,58 +28,58 @@ public abstract class AbstractVfsComponent implements VfsComponent {
     private Log log;
 
     /**
-     * Sets the Logger to use for the component.
-     *
-     * @param log The Log to use.
+     * Closes the provider. This implementation does nothing.
      */
     @Override
-    public final void setLogger(final Log log) {
-        this.log = log;
+    public void close() {
+        // default is noop.
     }
 
     /**
-     * Sets the context for this file system provider.
+     * Returns the context for this provider.
      *
-     * @param context The VfsComponentContext.
+     * @return provider context
      */
-    @Override
-    public final void setContext(final VfsComponentContext context) {
-        this.context = context;
+    protected final VfsComponentContext getContext() {
+        return context;
     }
 
     /**
-     * Initializes the component. This implementation does nothing.
+     * Returns the logger for this file system to use.
      *
-     * @throws FileSystemException if an error occurs.
+     * @return logger for this file system
      */
-    @Override
-    public void init() throws FileSystemException {
-        // default is noop.
+    protected final Log getLogger() {
+        return log;
     }
 
     /**
-     * Closes the provider. This implementation does nothing.
+     * Initializes the component. This implementation does nothing.
+     *
+     * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void close() {
+    public void init() throws FileSystemException {
         // default is noop.
     }
 
     /**
-     * Returns the logger for this file system to use.
+     * Sets the context for this file system provider.
      *
-     * @return logger for this file system
+     * @param context The VfsComponentContext.
      */
-    protected final Log getLogger() {
-        return log;
+    @Override
+    public final void setContext(final VfsComponentContext context) {
+        this.context = context;
     }
 
     /**
-     * Returns the context for this provider.
+     * Sets the Logger to use for the component.
      *
-     * @return provider context
+     * @param log The Log to use.
      */
-    protected final VfsComponentContext getContext() {
-        return context;
+    @Override
+    public final void setLogger(final Log log) {
+        this.log = log;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsContainer.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsContainer.java
index 3c8573f..1f484e9 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsContainer.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/AbstractVfsContainer.java
@@ -59,18 +59,6 @@ public abstract class AbstractVfsContainer extends AbstractVfsComponent {
     }
 
     /**
-     * Removes a sub-component from this component.
-     *
-     * @param component the component to remove.
-     */
-    protected void removeComponent(final Object component) {
-        synchronized (components) {
-            // multiple instances should not happen
-            components.remove(component);
-        }
-    }
-
-    /**
      * Closes the sub-components of this component.
      */
     @Override
@@ -85,4 +73,16 @@ public abstract class AbstractVfsContainer extends AbstractVfsComponent {
         Stream.of(toclose).filter(component -> component instanceof VfsComponent)
                           .forEach(component -> ((VfsComponent) component).close());
     }
+
+    /**
+     * Removes a sub-component from this component.
+     *
+     * @param component the component to remove.
+     */
+    protected void removeComponent(final Object component) {
+        synchronized (components) {
+            // multiple instances should not happen
+            components.remove(component);
+        }
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/CompositeFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/CompositeFileProvider.java
index 5d337f9..487af81 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/CompositeFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/CompositeFileProvider.java
@@ -36,13 +36,6 @@ public abstract class CompositeFileProvider extends AbstractFileProvider {
     }
 
     /**
-     * The schemes known.
-     *
-     * @return Array of supported schemes.
-     */
-    protected abstract String[] getSchemes();
-
-    /**
      * Locates a file object, by absolute URI.
      *
      * @param baseFile The base FileObject.
@@ -61,4 +54,11 @@ public abstract class CompositeFileProvider extends AbstractFileProvider {
 
         return getContext().getFileSystemManager().resolveFile(buf.toString(), fileSystemOptions);
     }
+
+    /**
+     * The schemes known.
+     *
+     * @return Array of supported schemes.
+     */
+    protected abstract String[] getSchemes();
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileContent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileContent.java
index 3f43f2b..7225d3b 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileContent.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileContent.java
@@ -48,22 +48,184 @@ public final class DefaultFileContent implements FileContent {
      * final int STATE_RANDOM_ACCESS = 3;
      */
 
+    /**
+     * An input stream for reading content. Provides buffering, and end-of-stream monitoring.
+     */
+    private final class FileContentInputStream extends MonitorInputStream {
+        // avoid gc
+        private final FileObject file;
+
+        FileContentInputStream(final FileObject file, final InputStream instr) {
+            super(instr);
+            this.file = file;
+        }
+
+        FileContentInputStream(final FileObject file, final InputStream instr, final int bufferSize) {
+            super(instr, bufferSize);
+            this.file = file;
+        }
+
+        /**
+         * Closes this input stream.
+         */
+        @Override
+        public void close() throws FileSystemException {
+            try {
+                super.close();
+            } catch (final IOException e) {
+                throw new FileSystemException("vfs.provider/close-instr.error", file, e);
+            }
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        @Override
+        protected void onClose() throws IOException {
+            try {
+                super.onClose();
+            } finally {
+                endInput(this);
+            }
+        }
+    }
+    /**
+     * An output stream for writing content.
+     */
+    final class FileContentOutputStream extends MonitorOutputStream {
+        // avoid gc
+        private final FileObject file;
+
+        FileContentOutputStream(final FileObject file, final OutputStream outstr) {
+            super(outstr);
+            this.file = file;
+        }
+
+        FileContentOutputStream(final FileObject file, final OutputStream outstr, final int bufferSize) {
+            super(outstr, bufferSize);
+            this.file = file;
+        }
+
+        /**
+         * Closes this output stream.
+         */
+        @Override
+        public void close() throws FileSystemException {
+            try {
+                super.close();
+            } catch (final IOException e) {
+                throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
+            }
+        }
+
+        /**
+         * Called after this stream is closed.
+         */
+        @Override
+        protected void onClose() throws IOException {
+            try {
+                super.onClose();
+            } finally {
+                try {
+                    endOutput();
+                } catch (final Exception e) {
+                    throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
+                }
+            }
+        }
+    }
+    /**
+     * An input/output stream for reading/writing content on random positions
+     */
+    private final class FileRandomAccessContent extends MonitorRandomAccessContent {
+        // also avoids gc
+        private final FileObject file;
+
+        FileRandomAccessContent(final FileObject file, final RandomAccessContent content) {
+            super(content);
+            this.file = file;
+        }
+
+        @Override
+        public void close() throws FileSystemException {
+            try {
+                super.close();
+            } catch (final IOException e) {
+                throw new FileSystemException("vfs.provider/close-rac.error", file, e);
+            }
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        @Override
+        protected void onClose() throws IOException {
+            try {
+                super.onClose();
+            } finally {
+                endRandomAccess(this);
+            }
+        }
+    }
+
+    /**
+     * An input stream for reading content. Provides buffering, and end-of-stream monitoring.
+     * <p>
+     * This is the same as {@link FileContentInputStream} but without the buffering.
+     * </p>
+     */
+    private final class RawFileContentInputStream extends RawMonitorInputStream {
+        // avoid gc
+        private final FileObject file;
+
+        RawFileContentInputStream(final FileObject file, final InputStream instr) {
+            super(instr);
+            this.file = file;
+        }
+
+        /**
+         * Closes this input stream.
+         */
+        @Override
+        public void close() throws FileSystemException {
+            try {
+                super.close();
+            } catch (final IOException e) {
+                throw new FileSystemException("vfs.provider/close-instr.error", file, e);
+            }
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        @Override
+        protected void onClose() throws IOException {
+            try {
+                super.onClose();
+            } finally {
+                endInput(this);
+            }
+        }
+    }
+
     private static final Certificate[] EMPTY_CERTIFICATE_ARRAY = {};
     static final int STATE_CLOSED = 0;
     static final int STATE_OPENED = 1;
-
     /**
      * The default buffer size for {@link #write(OutputStream)}.
      */
     private static final int WRITE_BUFFER_SIZE = 4096;
-
     private final AbstractFileObject<?> fileObject;
+
     private Map<String, Object> attrs;
     private Map<String, Object> roAttrs;
+
     private FileContentInfo fileContentInfo;
+
     private final FileContentInfoFactory fileContentInfoFactory;
 
     private final ThreadLocal<FileContentThreadData> threadLocal = ThreadLocal.withInitial(FileContentThreadData::new);
+
     private boolean resetAttributes;
 
     /**
@@ -82,172 +244,165 @@ public final class DefaultFileContent implements FileContent {
         this.fileContentInfoFactory = fileContentInfoFactory;
     }
 
-    private FileContentThreadData getFileContentThreadData() {
-        return this.threadLocal.get();
-    }
-
-    void streamOpened() {
-        synchronized (this) {
-            openStreams++;
-        }
-        ((AbstractFileSystem) fileObject.getFileSystem()).streamOpened();
-    }
+    private InputStream buildInputStream(final int bufferSize) throws FileSystemException {
+        /*
+         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw new
+         * FileSystemException("vfs.provider/read-in-use.error", file); }
+         */
+        // Get the raw input stream
+        // @formatter:off
+        final InputStream inputStream = bufferSize == 0
+                ? fileObject.getInputStream()
+                : fileObject.getInputStream(bufferSize);
+        // @formatter:on
+        // Double buffering may take place here.
+//        final InputStream wrappedInputStream = bufferSize == 0
+//                    ? new FileContentInputStream(fileObject, inputStream)
+//                    : new FileContentInputStream(fileObject, inputStream, bufferSize);
 
-    void streamClosed() {
-        synchronized (this) {
-            if (openStreams > 0) {
-                openStreams--;
-                if (openStreams < 1) {
-                    fileObject.notifyAllStreamsClosed();
-                }
-            }
+        final InputStream wrappedInputStream;
+        if (inputStream instanceof BufferedInputStream) {
+            // Don't double buffer.
+            wrappedInputStream = new RawFileContentInputStream(fileObject, inputStream);
+        } else {
+            // @formatter:off
+            wrappedInputStream = bufferSize == 0
+                    ? new FileContentInputStream(fileObject, inputStream)
+                    : new FileContentInputStream(fileObject, inputStream, bufferSize);
+            // @formatter:on
         }
-        ((AbstractFileSystem) fileObject.getFileSystem()).streamClosed();
-    }
+        getFileContentThreadData().add(wrappedInputStream);
+        streamOpened();
 
-    /**
-     * Returns the file that this is the content of.
-     *
-     * @return the FileObject.
-     */
-    @Override
-    public FileObject getFile() {
-        return fileObject;
+        return wrappedInputStream;
     }
 
-    /**
-     * Returns the size of the content (in bytes).
-     *
-     * @return The size of the content (in bytes).
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public long getSize() throws FileSystemException {
-        // Do some checking
-        if (!fileObject.getType().hasContent()) {
-            throw new FileSystemException("vfs.provider/get-size-not-file.error", fileObject);
-        }
+    private OutputStream buildOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException {
         /*
-         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
-         * new FileSystemException("vfs.provider/get-size-write.error", file); }
+         * if (getThreadData().getState() != STATE_NONE)
          */
+        final FileContentThreadData threadData = getFileContentThreadData();
 
-        try {
-            // Get the size
-            return fileObject.doGetContentSize();
-        } catch (final Exception exc) {
-            throw new FileSystemException("vfs.provider/get-size.error", exc, fileObject);
+        if (threadData.getOutputStream() != null) {
+            throw new FileSystemException("vfs.provider/write-in-use.error", fileObject);
         }
-    }
 
-    /**
-     * Returns the last-modified timestamp.
-     *
-     * @return The last modified timestamp.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public long getLastModifiedTime() throws FileSystemException {
-        /*
-         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
-         * new FileSystemException("vfs.provider/get-last-modified-writing.error", file); }
-         */
-        if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/get-last-modified-no-exist.error", fileObject);
-        }
-        try {
-            return fileObject.doGetLastModifiedTime();
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.provider/get-last-modified.error", fileObject, e);
-        }
+        // Get the raw output stream
+        final OutputStream outstr = fileObject.getOutputStream(bAppend);
+
+        // Create and set wrapper
+        final FileContentOutputStream wrapped = bufferSize == 0 ?
+            new FileContentOutputStream(fileObject, outstr) :
+            new FileContentOutputStream(fileObject, outstr, bufferSize);
+        threadData.setOutputStream(wrapped);
+        streamOpened();
+
+        return wrapped;
     }
 
     /**
-     * Sets the last-modified timestamp.
+     * Closes all resources used by the content, including all streams, readers and writers.
      *
-     * @param modTime The last modified timestamp.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void setLastModifiedTime(final long modTime) throws FileSystemException {
-        /*
-         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
-         * new FileSystemException("vfs.provider/set-last-modified-writing.error", file); }
-         */
-        if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/set-last-modified-no-exist.error", fileObject);
-        }
+    public void close() throws FileSystemException {
+        FileSystemException caught = null;
         try {
-            if (!fileObject.doSetLastModifiedTime(modTime)) {
-                throw new FileSystemException("vfs.provider/set-last-modified.error", fileObject);
+            final FileContentThreadData threadData = getFileContentThreadData();
+
+            // Close the input stream
+            while (threadData.hasInputStream()) {
+                final InputStream inputStream = threadData.removeInputStream(0);
+                try {
+                    if (inputStream instanceof FileContentInputStream) {
+                        ((FileContentInputStream) inputStream).close();
+                    } else if (inputStream instanceof RawFileContentInputStream) {
+                        ((RawFileContentInputStream) inputStream).close();
+                    } else {
+                       caught = new FileSystemException("Unsupported InputStream type: " + inputStream);
+                    }
+                } catch (final FileSystemException ex) {
+                    caught = ex;
+
+                }
             }
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.provider/set-last-modified.error", fileObject, e);
+
+            // Close the randomAccess stream
+            while (threadData.hasRandomAccessContent()) {
+                final FileRandomAccessContent randomAccessContent = (FileRandomAccessContent) threadData
+                        .removeRandomAccessContent(0);
+                try {
+                    randomAccessContent.close();
+                } catch (final FileSystemException ex) {
+                    caught = ex;
+                }
+            }
+
+            // Close the output stream
+            final FileContentOutputStream outputStream = threadData.getOutputStream();
+            if (outputStream != null) {
+                threadData.setOutputStream(null);
+                try {
+                    outputStream.close();
+                } catch (final FileSystemException ex) {
+                    caught = ex;
+                }
+            }
+        } finally {
+            threadLocal.remove();
         }
-    }
 
-    /**
-     * Checks if an attribute exists.
-     *
-     * @param attrName The name of the attribute to check.
-     * @return true if the attribute is associated with the file.
-     * @throws FileSystemException if an error occurs.
-     * @since 2.0
-     */
-    @Override
-    public boolean hasAttribute(final String attrName) throws FileSystemException {
-        if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/exists-attributes-no-exist.error", fileObject);
+        // throw last error (out >> rac >> input) after all closes have been tried
+        if (caught != null) {
+            throw caught;
         }
-        getAttributes();
-        return attrs.containsKey(attrName);
     }
 
     /**
-     * Returns a read-only map of this file's attributes.
-     *
-     * @return a Map of the file's attributes.
-     * @throws FileSystemException if an error occurs.
+     * Handles the end of input stream.
      */
-    @Override
-    public Map<String, Object> getAttributes() throws FileSystemException {
-        if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/get-attributes-no-exist.error", fileObject);
+    private void endInput(final InputStream instr) {
+        final FileContentThreadData fileContentThreadData = threadLocal.get();
+        if (fileContentThreadData != null) {
+            fileContentThreadData.remove(instr);
         }
-        if (resetAttributes || roAttrs == null) {
-            try {
-                synchronized (this) {
-                    attrs = fileObject.doGetAttributes();
-                    roAttrs = Collections.unmodifiableMap(attrs);
-                    resetAttributes = false;
-                }
-            } catch (final Exception e) {
-                throw new FileSystemException("vfs.provider/get-attributes.error", fileObject, e);
-            }
+        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
+            // remove even when no value is set to remove key
+            threadLocal.remove();
         }
-        return roAttrs;
+        streamClosed();
     }
 
     /**
-     * Used internally to flag situations where the file attributes should be reretrieved.
-     *
-     * @since 2.0
+     * Handles the end of output stream.
      */
-    public void resetAttributes() {
-        resetAttributes = true;
+    private void endOutput() throws Exception {
+        final FileContentThreadData fileContentThreadData = threadLocal.get();
+        if (fileContentThreadData != null) {
+            fileContentThreadData.setOutputStream(null);
+        }
+        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
+            // remove even when no value is set to remove key
+            threadLocal.remove();
+        }
+        streamClosed();
+        fileObject.endOutput();
     }
 
     /**
-     * Lists the attributes of this file.
-     *
-     * @return An array of attribute names.
-     * @throws FileSystemException if an error occurs.
+     * Handles the end of random access.
      */
-    @Override
-    public String[] getAttributeNames() throws FileSystemException {
-        getAttributes();
-        final Set<String> names = attrs.keySet();
-        return names.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
+    private void endRandomAccess(final RandomAccessContent rac) {
+        final FileContentThreadData fileContentThreadData = threadLocal.get();
+        if (fileContentThreadData != null) {
+            fileContentThreadData.remove(rac);
+        }
+        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
+            // remove even when no value is set to remove key
+            threadLocal.remove();
+        }
+        streamClosed();
     }
 
     /**
@@ -264,50 +419,41 @@ public final class DefaultFileContent implements FileContent {
     }
 
     /**
-     * Sets the value of an attribute.
+     * Lists the attributes of this file.
      *
-     * @param attrName The name of the attribute to add.
-     * @param value The value of the attribute.
+     * @return An array of attribute names.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void setAttribute(final String attrName, final Object value) throws FileSystemException {
-        if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/set-attribute-no-exist.error", attrName, fileObject);
-        }
-        try {
-            fileObject.doSetAttribute(attrName, value);
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.provider/set-attribute.error", e, attrName, fileObject);
-        }
-
-        if (attrs != null) {
-            attrs.put(attrName, value);
-        }
+    public String[] getAttributeNames() throws FileSystemException {
+        getAttributes();
+        final Set<String> names = attrs.keySet();
+        return names.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
     }
 
     /**
-     * Removes an attribute.
+     * Returns a read-only map of this file's attributes.
      *
-     * @param attrName The name of the attribute to remove.
+     * @return a Map of the file's attributes.
      * @throws FileSystemException if an error occurs.
-     * @since 2.0
      */
     @Override
-    public void removeAttribute(final String attrName) throws FileSystemException {
+    public Map<String, Object> getAttributes() throws FileSystemException {
         if (!fileObject.getType().hasAttributes()) {
-            throw new FileSystemException("vfs.provider/remove-attribute-no-exist.error", fileObject);
-        }
-
-        try {
-            fileObject.doRemoveAttribute(attrName);
-        } catch (final Exception e) {
-            throw new FileSystemException("vfs.provider/remove-attribute.error", e, attrName, fileObject);
+            throw new FileSystemException("vfs.provider/get-attributes-no-exist.error", fileObject);
         }
-
-        if (attrs != null) {
-            attrs.remove(attrName);
+        if (resetAttributes || roAttrs == null) {
+            try {
+                synchronized (this) {
+                    attrs = fileObject.doGetAttributes();
+                    roAttrs = Collections.unmodifiableMap(attrs);
+                    resetAttributes = false;
+                }
+            } catch (final Exception e) {
+                throw new FileSystemException("vfs.provider/get-attributes.error", fileObject, e);
+            }
         }
+        return roAttrs;
     }
 
     /**
@@ -338,6 +484,35 @@ public final class DefaultFileContent implements FileContent {
     }
 
     /**
+     * Gets the FileContentInfo which describes the content-type, content-encoding.
+     *
+     * @return The FileContentInfo.
+     * @throws FileSystemException if an error occurs.
+     */
+    @Override
+    public FileContentInfo getContentInfo() throws FileSystemException {
+        if (fileContentInfo == null) {
+            fileContentInfo = fileContentInfoFactory.create(this);
+        }
+
+        return fileContentInfo;
+    }
+
+    /**
+     * Returns the file that this is the content of.
+     *
+     * @return the FileObject.
+     */
+    @Override
+    public FileObject getFile() {
+        return fileObject;
+    }
+
+    private FileContentThreadData getFileContentThreadData() {
+        return this.threadLocal.get();
+    }
+
+    /**
      * Returns an input stream for reading the content.
      *
      * @return The InputStream
@@ -362,28 +537,25 @@ public final class DefaultFileContent implements FileContent {
     }
 
     /**
-     * Returns an input/output stream to use to read and write the content of the file in an random manner.
+     * Returns the last-modified timestamp.
      *
-     * @param mode The RandomAccessMode.
-     * @return A RandomAccessContent object to access the file.
+     * @return The last modified timestamp.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException {
+    public long getLastModifiedTime() throws FileSystemException {
         /*
-         * if (getThreadData().getState() != STATE_NONE) { throw new
-         * FileSystemException("vfs.provider/read-in-use.error", file); }
+         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
+         * new FileSystemException("vfs.provider/get-last-modified-writing.error", file); }
          */
-
-        // Get the content
-        final RandomAccessContent rastr = fileObject.getRandomAccessContent(mode);
-
-        final FileRandomAccessContent rac = new FileRandomAccessContent(fileObject, rastr);
-
-        getFileContentThreadData().add(rac);
-        streamOpened();
-
-        return rac;
+        if (!fileObject.getType().hasAttributes()) {
+            throw new FileSystemException("vfs.provider/get-last-modified-no-exist.error", fileObject);
+        }
+        try {
+            return fileObject.doGetLastModifiedTime();
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider/get-last-modified.error", fileObject, e);
+        }
     }
 
     /**
@@ -410,191 +582,97 @@ public final class DefaultFileContent implements FileContent {
     }
 
     /**
-     * Returns an output stream for writing the content.
+     * Returns an output stream for writing the content in append mode.
      *
+     * @param bAppend true if the data written should be appended.
      * @param bufferSize The buffer size to use.
      * @return The OutputStream for the file.
      * @throws FileSystemException if an error occurs.
      * @since 2.4
      */
     @Override
-    public OutputStream getOutputStream(final int bufferSize) throws FileSystemException {
-        return buildOutputStream(false, bufferSize);
+    public OutputStream getOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException {
+        return buildOutputStream(bAppend, bufferSize);
     }
 
     /**
-     * Returns an output stream for writing the content in append mode.
+     * Returns an output stream for writing the content.
      *
-     * @param bAppend true if the data written should be appended.
      * @param bufferSize The buffer size to use.
      * @return The OutputStream for the file.
      * @throws FileSystemException if an error occurs.
      * @since 2.4
      */
     @Override
-    public OutputStream getOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException {
-        return buildOutputStream(bAppend, bufferSize);
+    public OutputStream getOutputStream(final int bufferSize) throws FileSystemException {
+        return buildOutputStream(false, bufferSize);
     }
 
     /**
-     * Closes all resources used by the content, including all streams, readers and writers.
+     * Returns an input/output stream to use to read and write the content of the file in an random manner.
      *
+     * @param mode The RandomAccessMode.
+     * @return A RandomAccessContent object to access the file.
      * @throws FileSystemException if an error occurs.
      */
     @Override
-    public void close() throws FileSystemException {
-        FileSystemException caught = null;
-        try {
-            final FileContentThreadData threadData = getFileContentThreadData();
-
-            // Close the input stream
-            while (threadData.hasInputStream()) {
-                final InputStream inputStream = threadData.removeInputStream(0);
-                try {
-                    if (inputStream instanceof FileContentInputStream) {
-                        ((FileContentInputStream) inputStream).close();
-                    } else if (inputStream instanceof RawFileContentInputStream) {
-                        ((RawFileContentInputStream) inputStream).close();
-                    } else {
-                       caught = new FileSystemException("Unsupported InputStream type: " + inputStream);
-                    }
-                } catch (final FileSystemException ex) {
-                    caught = ex;
-
-                }
-            }
-
-            // Close the randomAccess stream
-            while (threadData.hasRandomAccessContent()) {
-                final FileRandomAccessContent randomAccessContent = (FileRandomAccessContent) threadData
-                        .removeRandomAccessContent(0);
-                try {
-                    randomAccessContent.close();
-                } catch (final FileSystemException ex) {
-                    caught = ex;
-                }
-            }
-
-            // Close the output stream
-            final FileContentOutputStream outputStream = threadData.getOutputStream();
-            if (outputStream != null) {
-                threadData.setOutputStream(null);
-                try {
-                    outputStream.close();
-                } catch (final FileSystemException ex) {
-                    caught = ex;
-                }
-            }
-        } finally {
-            threadLocal.remove();
-        }
-
-        // throw last error (out >> rac >> input) after all closes have been tried
-        if (caught != null) {
-            throw caught;
-        }
-    }
-
-    private InputStream buildInputStream(final int bufferSize) throws FileSystemException {
+    public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException {
         /*
-         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw new
+         * if (getThreadData().getState() != STATE_NONE) { throw new
          * FileSystemException("vfs.provider/read-in-use.error", file); }
          */
-        // Get the raw input stream
-        // @formatter:off
-        final InputStream inputStream = bufferSize == 0
-                ? fileObject.getInputStream()
-                : fileObject.getInputStream(bufferSize);
-        // @formatter:on
-        // Double buffering may take place here.
-//        final InputStream wrappedInputStream = bufferSize == 0
-//                    ? new FileContentInputStream(fileObject, inputStream)
-//                    : new FileContentInputStream(fileObject, inputStream, bufferSize);
-
-        final InputStream wrappedInputStream;
-        if (inputStream instanceof BufferedInputStream) {
-            // Don't double buffer.
-            wrappedInputStream = new RawFileContentInputStream(fileObject, inputStream);
-        } else {
-            // @formatter:off
-            wrappedInputStream = bufferSize == 0
-                    ? new FileContentInputStream(fileObject, inputStream)
-                    : new FileContentInputStream(fileObject, inputStream, bufferSize);
-            // @formatter:on
-        }
-        getFileContentThreadData().add(wrappedInputStream);
-        streamOpened();
-
-        return wrappedInputStream;
-    }
-
-    private OutputStream buildOutputStream(final boolean bAppend, final int bufferSize) throws FileSystemException {
-        /*
-         * if (getThreadData().getState() != STATE_NONE)
-         */
-        final FileContentThreadData threadData = getFileContentThreadData();
 
-        if (threadData.getOutputStream() != null) {
-            throw new FileSystemException("vfs.provider/write-in-use.error", fileObject);
-        }
+        // Get the content
+        final RandomAccessContent rastr = fileObject.getRandomAccessContent(mode);
 
-        // Get the raw output stream
-        final OutputStream outstr = fileObject.getOutputStream(bAppend);
+        final FileRandomAccessContent rac = new FileRandomAccessContent(fileObject, rastr);
 
-        // Create and set wrapper
-        final FileContentOutputStream wrapped = bufferSize == 0 ?
-            new FileContentOutputStream(fileObject, outstr) :
-            new FileContentOutputStream(fileObject, outstr, bufferSize);
-        threadData.setOutputStream(wrapped);
+        getFileContentThreadData().add(rac);
         streamOpened();
 
-        return wrapped;
-    }
-
-    /**
-     * Handles the end of input stream.
-     */
-    private void endInput(final InputStream instr) {
-        final FileContentThreadData fileContentThreadData = threadLocal.get();
-        if (fileContentThreadData != null) {
-            fileContentThreadData.remove(instr);
-        }
-        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
-            // remove even when no value is set to remove key
-            threadLocal.remove();
-        }
-        streamClosed();
+        return rac;
     }
 
     /**
-     * Handles the end of random access.
+     * Returns the size of the content (in bytes).
+     *
+     * @return The size of the content (in bytes).
+     * @throws FileSystemException if an error occurs.
      */
-    private void endRandomAccess(final RandomAccessContent rac) {
-        final FileContentThreadData fileContentThreadData = threadLocal.get();
-        if (fileContentThreadData != null) {
-            fileContentThreadData.remove(rac);
+    @Override
+    public long getSize() throws FileSystemException {
+        // Do some checking
+        if (!fileObject.getType().hasContent()) {
+            throw new FileSystemException("vfs.provider/get-size-not-file.error", fileObject);
         }
-        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
-            // remove even when no value is set to remove key
-            threadLocal.remove();
+        /*
+         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
+         * new FileSystemException("vfs.provider/get-size-write.error", file); }
+         */
+
+        try {
+            // Get the size
+            return fileObject.doGetContentSize();
+        } catch (final Exception exc) {
+            throw new FileSystemException("vfs.provider/get-size.error", exc, fileObject);
         }
-        streamClosed();
     }
 
     /**
-     * Handles the end of output stream.
+     * Checks if an attribute exists.
+     *
+     * @param attrName The name of the attribute to check.
+     * @return true if the attribute is associated with the file.
+     * @throws FileSystemException if an error occurs.
+     * @since 2.0
      */
-    private void endOutput() throws Exception {
-        final FileContentThreadData fileContentThreadData = threadLocal.get();
-        if (fileContentThreadData != null) {
-            fileContentThreadData.setOutputStream(null);
-        }
-        if (fileContentThreadData == null || !fileContentThreadData.hasStreams()) {
-            // remove even when no value is set to remove key
-            threadLocal.remove();
+    @Override
+    public boolean hasAttribute(final String attrName) throws FileSystemException {
+        if (!fileObject.getType().hasAttributes()) {
+            throw new FileSystemException("vfs.provider/exists-attributes-no-exist.error", fileObject);
         }
-        streamClosed();
-        fileObject.endOutput();
+        getAttributes();
+        return attrs.containsKey(attrName);
     }
 
     /**
@@ -628,180 +706,102 @@ public final class DefaultFileContent implements FileContent {
     }
 
     /**
-     * An input stream for reading content. Provides buffering, and end-of-stream monitoring.
+     * Removes an attribute.
+     *
+     * @param attrName The name of the attribute to remove.
+     * @throws FileSystemException if an error occurs.
+     * @since 2.0
      */
-    private final class FileContentInputStream extends MonitorInputStream {
-        // avoid gc
-        private final FileObject file;
-
-        FileContentInputStream(final FileObject file, final InputStream instr) {
-            super(instr);
-            this.file = file;
-        }
-
-        FileContentInputStream(final FileObject file, final InputStream instr, final int bufferSize) {
-            super(instr, bufferSize);
-            this.file = file;
+    @Override
+    public void removeAttribute(final String attrName) throws FileSystemException {
+        if (!fileObject.getType().hasAttributes()) {
+            throw new FileSystemException("vfs.provider/remove-attribute-no-exist.error", fileObject);
         }
 
-        /**
-         * Closes this input stream.
-         */
-        @Override
-        public void close() throws FileSystemException {
-            try {
-                super.close();
-            } catch (final IOException e) {
-                throw new FileSystemException("vfs.provider/close-instr.error", file, e);
-            }
+        try {
+            fileObject.doRemoveAttribute(attrName);
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider/remove-attribute.error", e, attrName, fileObject);
         }
 
-        /**
-         * Called after the stream has been closed.
-         */
-        @Override
-        protected void onClose() throws IOException {
-            try {
-                super.onClose();
-            } finally {
-                endInput(this);
-            }
+        if (attrs != null) {
+            attrs.remove(attrName);
         }
     }
 
     /**
-     * An input stream for reading content. Provides buffering, and end-of-stream monitoring.
-     * <p>
-     * This is the same as {@link FileContentInputStream} but without the buffering.
-     * </p>
+     * Used internally to flag situations where the file attributes should be reretrieved.
+     *
+     * @since 2.0
      */
-    private final class RawFileContentInputStream extends RawMonitorInputStream {
-        // avoid gc
-        private final FileObject file;
-
-        RawFileContentInputStream(final FileObject file, final InputStream instr) {
-            super(instr);
-            this.file = file;
-        }
-
-        /**
-         * Closes this input stream.
-         */
-        @Override
-        public void close() throws FileSystemException {
-            try {
-                super.close();
-            } catch (final IOException e) {
-                throw new FileSystemException("vfs.provider/close-instr.error", file, e);
-            }
-        }
-
-        /**
-         * Called after the stream has been closed.
-         */
-        @Override
-        protected void onClose() throws IOException {
-            try {
-                super.onClose();
-            } finally {
-                endInput(this);
-            }
-        }
+    public void resetAttributes() {
+        resetAttributes = true;
     }
 
     /**
-     * An input/output stream for reading/writing content on random positions
+     * Sets the value of an attribute.
+     *
+     * @param attrName The name of the attribute to add.
+     * @param value The value of the attribute.
+     * @throws FileSystemException if an error occurs.
      */
-    private final class FileRandomAccessContent extends MonitorRandomAccessContent {
-        // also avoids gc
-        private final FileObject file;
-
-        FileRandomAccessContent(final FileObject file, final RandomAccessContent content) {
-            super(content);
-            this.file = file;
+    @Override
+    public void setAttribute(final String attrName, final Object value) throws FileSystemException {
+        if (!fileObject.getType().hasAttributes()) {
+            throw new FileSystemException("vfs.provider/set-attribute-no-exist.error", attrName, fileObject);
         }
-
-        /**
-         * Called after the stream has been closed.
-         */
-        @Override
-        protected void onClose() throws IOException {
-            try {
-                super.onClose();
-            } finally {
-                endRandomAccess(this);
-            }
+        try {
+            fileObject.doSetAttribute(attrName, value);
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider/set-attribute.error", e, attrName, fileObject);
         }
 
-        @Override
-        public void close() throws FileSystemException {
-            try {
-                super.close();
-            } catch (final IOException e) {
-                throw new FileSystemException("vfs.provider/close-rac.error", file, e);
-            }
+        if (attrs != null) {
+            attrs.put(attrName, value);
         }
     }
 
     /**
-     * An output stream for writing content.
+     * Sets the last-modified timestamp.
+     *
+     * @param modTime The last modified timestamp.
+     * @throws FileSystemException if an error occurs.
      */
-    final class FileContentOutputStream extends MonitorOutputStream {
-        // avoid gc
-        private final FileObject file;
-
-        FileContentOutputStream(final FileObject file, final OutputStream outstr) {
-            super(outstr);
-            this.file = file;
-        }
-
-        FileContentOutputStream(final FileObject file, final OutputStream outstr, final int bufferSize) {
-            super(outstr, bufferSize);
-            this.file = file;
-        }
-
-        /**
-         * Closes this output stream.
+    @Override
+    public void setLastModifiedTime(final long modTime) throws FileSystemException {
+        /*
+         * if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS) { throw
+         * new FileSystemException("vfs.provider/set-last-modified-writing.error", file); }
          */
-        @Override
-        public void close() throws FileSystemException {
-            try {
-                super.close();
-            } catch (final IOException e) {
-                throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
+        if (!fileObject.getType().hasAttributes()) {
+            throw new FileSystemException("vfs.provider/set-last-modified-no-exist.error", fileObject);
+        }
+        try {
+            if (!fileObject.doSetLastModifiedTime(modTime)) {
+                throw new FileSystemException("vfs.provider/set-last-modified.error", fileObject);
             }
+        } catch (final Exception e) {
+            throw new FileSystemException("vfs.provider/set-last-modified.error", fileObject, e);
         }
+    }
 
-        /**
-         * Called after this stream is closed.
-         */
-        @Override
-        protected void onClose() throws IOException {
-            try {
-                super.onClose();
-            } finally {
-                try {
-                    endOutput();
-                } catch (final Exception e) {
-                    throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
+    void streamClosed() {
+        synchronized (this) {
+            if (openStreams > 0) {
+                openStreams--;
+                if (openStreams < 1) {
+                    fileObject.notifyAllStreamsClosed();
                 }
             }
         }
+        ((AbstractFileSystem) fileObject.getFileSystem()).streamClosed();
     }
 
-    /**
-     * Gets the FileContentInfo which describes the content-type, content-encoding.
-     *
-     * @return The FileContentInfo.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public FileContentInfo getContentInfo() throws FileSystemException {
-        if (fileContentInfo == null) {
-            fileContentInfo = fileContentInfoFactory.create(this);
+    void streamOpened() {
+        synchronized (this) {
+            openStreams++;
         }
-
-        return fileContentInfo;
+        ((AbstractFileSystem) fileObject.getFileSystem()).streamOpened();
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileSelectorInfo.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileSelectorInfo.java
index e5b1219..9a96fff 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileSelectorInfo.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultFileSelectorInfo.java
@@ -33,8 +33,9 @@ final class DefaultFileSelectorInfo implements FileSelectInfo {
         return baseFolder;
     }
 
-    public void setBaseFolder(final FileObject baseFolder) {
-        this.baseFolder = baseFolder;
+    @Override
+    public int getDepth() {
+        return depth;
     }
 
     @Override
@@ -42,19 +43,18 @@ final class DefaultFileSelectorInfo implements FileSelectInfo {
         return file;
     }
 
-    public void setFile(final FileObject file) {
-        this.file = file;
-    }
-
-    @Override
-    public int getDepth() {
-        return depth;
+    public void setBaseFolder(final FileObject baseFolder) {
+        this.baseFolder = baseFolder;
     }
 
     public void setDepth(final int depth) {
         this.depth = depth;
     }
 
+    public void setFile(final FileObject file) {
+        this.file = file;
+    }
+
     @Override
     public String toString() {
         return super.toString() + " [baseFolder=" + baseFolder + ", file=" + file + ", depth=" + depth + "]";
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultURLConnection.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultURLConnection.java
index b8f4965..f6deeca 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultURLConnection.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DefaultURLConnection.java
@@ -49,21 +49,11 @@ public final class DefaultURLConnection extends URLConnection {
     }
 
     @Override
-    public InputStream getInputStream() throws IOException {
-        return fileContent.getInputStream();
-    }
-
-    @Override
-    public OutputStream getOutputStream() throws IOException {
-        return fileContent.getOutputStream();
-    }
-
-    @Override
-    public long getLastModified() {
+    public String getContentEncoding() {
         try {
-            return fileContent.getLastModifiedTime();
-        } catch (final FileSystemException ignored) {
-            return -1; // TODO: report?
+            return fileContent.getContentInfo().getContentEncoding();
+        } catch (final FileSystemException e) {
+            throw new RuntimeException(e.getMessage());
         }
     }
 
@@ -86,14 +76,24 @@ public final class DefaultURLConnection extends URLConnection {
     }
 
     @Override
-    public String getContentEncoding() {
+    public InputStream getInputStream() throws IOException {
+        return fileContent.getInputStream();
+    }
+
+    @Override
+    public long getLastModified() {
         try {
-            return fileContent.getContentInfo().getContentEncoding();
-        } catch (final FileSystemException e) {
-            throw new RuntimeException(e.getMessage());
+            return fileContent.getLastModifiedTime();
+        } catch (final FileSystemException ignored) {
+            return -1; // TODO: report?
         }
     }
 
+    @Override
+    public OutputStream getOutputStream() throws IOException {
+        return fileContent.getOutputStream();
+    }
+
     /*
      * public String getHeaderField(String name) { try { if
      * (content.getFile().getFileSystem().hasCapability(Capability.ATTRIBUTES)) { String value = (String)
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DelegateFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DelegateFileObject.java
index c293b43..6d6cd48 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DelegateFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/DelegateFileObject.java
@@ -68,16 +68,6 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Get access to the delegated file.
-     *
-     * @return The FileObject.
-     * @since 2.0
-     */
-    public FileObject getDelegateFile() {
-        return file;
-    }
-
-    /**
      * Adds a child to this file.
      *
      * @param baseName The base FileName.
@@ -93,37 +83,116 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Attaches or detaches the target file.
+     * Close the delegated file.
      *
-     * @param file The FileObject.
-     * @throws Exception if an error occurs.
+     * @throws FileSystemException if an error occurs.
      */
-    public void setFile(final FileObject file) throws Exception {
-        final FileType oldType = doGetType();
+    @Override
+    public void close() throws FileSystemException {
+        super.close();
 
         if (file != null) {
-            WeakRefFileListener.installListener(file, this);
+            file.close();
         }
-        this.file = file;
-        maybeTypeChanged(oldType);
     }
 
     /**
-     * Checks whether the file's type has changed, and fires the appropriate events.
-     *
-     * @param oldType The old FileType.
-     * @throws Exception if an error occurs.
+     * Creates this file as a folder.
      */
-    private void maybeTypeChanged(final FileType oldType) throws Exception {
-        final FileType newType = doGetType();
-        if (oldType == FileType.IMAGINARY && newType != FileType.IMAGINARY) {
-            handleCreate(newType);
-        } else if (oldType != FileType.IMAGINARY && newType == FileType.IMAGINARY) {
-            handleDelete();
+    @Override
+    protected void doCreateFolder() throws Exception {
+        ignoreEvent = true;
+        try {
+            file.createFolder();
+        } finally {
+            ignoreEvent = false;
+        }
+    }
+
+    /**
+     * Deletes the file.
+     */
+    @Override
+    protected void doDelete() throws Exception {
+        ignoreEvent = true;
+        try {
+            file.delete();
+        } finally {
+            ignoreEvent = false;
         }
     }
 
     /**
+     * Returns the attributes of this file.
+     */
+    @Override
+    protected Map<String, Object> doGetAttributes() throws Exception {
+        return file.getContent().getAttributes();
+    }
+
+    /**
+     * Returns the certificates of this file.
+     */
+    @Override
+    protected Certificate[] doGetCertificates() throws Exception {
+        return file.getContent().getCertificates();
+    }
+
+    /**
+     * Return file content info.
+     *
+     * @return the file content info of the delegee.
+     * @throws Exception Any thrown Exception is wrapped in FileSystemException.
+     * @since 2.0
+     */
+    protected FileContentInfo doGetContentInfo() throws Exception {
+        return file.getContent().getContentInfo();
+    }
+
+    /**
+     * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
+     * {@link FileType#FILE}.
+     */
+    @Override
+    protected long doGetContentSize() throws Exception {
+        return file.getContent().getSize();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    @Override
+    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
+        return file.getContent().getInputStream(bufferSize);
+    }
+
+    /**
+     * Returns the last-modified time of this file.
+     */
+    @Override
+    protected long doGetLastModifiedTime() throws Exception {
+        return file.getContent().getLastModifiedTime();
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    @Override
+    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
+        return file.getContent().getOutputStream(bAppend);
+    }
+
+    /**
+     * Creates access to the file for random i/o.
+     *
+     * @since 2.0
+     */
+    @Override
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
+        return file.getContent().getRandomAccessContent(mode);
+    }
+
+    /**
      * Determines the type of the file, returns null if the file does not exist.
      */
     @Override
@@ -138,45 +207,45 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Determines if this file can be read.
+     * Determines if this file is executable.
      */
     @Override
-    protected boolean doIsReadable() throws FileSystemException {
+    protected boolean doIsExecutable() throws FileSystemException {
         if (file != null) {
-            return file.isReadable();
+            return file.isExecutable();
         }
-        return true;
+        return false;
     }
 
     /**
-     * Determines if this file can be written to.
+     * Determines if this file is hidden.
      */
     @Override
-    protected boolean doIsWriteable() throws FileSystemException {
+    protected boolean doIsHidden() throws FileSystemException {
         if (file != null) {
-            return file.isWriteable();
+            return file.isHidden();
         }
         return false;
     }
 
     /**
-     * Determines if this file is executable.
+     * Determines if this file can be read.
      */
     @Override
-    protected boolean doIsExecutable() throws FileSystemException {
+    protected boolean doIsReadable() throws FileSystemException {
         if (file != null) {
-            return file.isExecutable();
+            return file.isReadable();
         }
-        return false;
+        return true;
     }
 
     /**
-     * Determines if this file is hidden.
+     * Determines if this file can be written to.
      */
     @Override
-    protected boolean doIsHidden() throws FileSystemException {
+    protected boolean doIsWriteable() throws FileSystemException {
         if (file != null) {
-            return file.isHidden();
+            return file.isWriteable();
         }
         return false;
     }
@@ -202,46 +271,25 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Creates this file as a folder.
-     */
-    @Override
-    protected void doCreateFolder() throws Exception {
-        ignoreEvent = true;
-        try {
-            file.createFolder();
-        } finally {
-            ignoreEvent = false;
-        }
-    }
-
-    /**
-     * Deletes the file.
-     */
-    @Override
-    protected void doDelete() throws Exception {
-        ignoreEvent = true;
-        try {
-            file.delete();
-        } finally {
-            ignoreEvent = false;
-        }
-    }
-
-    /**
-     * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
-     * {@link FileType#FILE}.
+     * Removes an attribute of this file.
+     *
+     * @since 2.0
      */
     @Override
-    protected long doGetContentSize() throws Exception {
-        return file.getContent().getSize();
+    protected void doRemoveAttribute(final String atttrName) throws Exception {
+        file.getContent().removeAttribute(atttrName);
     }
 
     /**
-     * Returns the attributes of this file.
+     * Renames the file.
+     *
+     * @param newFile the new location/name.
+     * @throws Exception Any thrown Exception is wrapped in FileSystemException.
+     * @since 2.0
      */
     @Override
-    protected Map<String, Object> doGetAttributes() throws Exception {
-        return file.getContent().getAttributes();
+    protected void doRename(final FileObject newFile) throws Exception {
+        file.moveTo(((DelegateFileObject) newFile).file);
     }
 
     /**
@@ -253,22 +301,6 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Returns the certificates of this file.
-     */
-    @Override
-    protected Certificate[] doGetCertificates() throws Exception {
-        return file.getContent().getCertificates();
-    }
-
-    /**
-     * Returns the last-modified time of this file.
-     */
-    @Override
-    protected long doGetLastModifiedTime() throws Exception {
-        return file.getContent().getLastModifiedTime();
-    }
-
-    /**
      * Sets the last-modified time of this file.
      *
      * @since 2.0
@@ -280,19 +312,22 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Creates an input stream to read the file content from.
-     */
-    @Override
-    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
-        return file.getContent().getInputStream(bufferSize);
-    }
-
-    /**
-     * Creates an output stream to write the file content to.
+     * Called when a file is changed.
+     * <p>
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
+     * </p>
+     *
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
      */
     @Override
-    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
-        return file.getContent().getOutputStream(bAppend);
+    public void fileChanged(final FileChangeEvent event) throws Exception {
+        if (event.getFileObject() != file) {
+            return;
+        }
+        if (!ignoreEvent) {
+            handleChanged();
+        }
     }
 
     /**
@@ -328,35 +363,27 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Called when a file is changed.
-     * <p>
-     * This will only happen if you monitor the file using {@link org.apache.commons.vfs2.FileMonitor}.
-     * </p>
+     * Get access to the delegated file.
      *
-     * @param event The FileChangeEvent.
-     * @throws Exception if an error occurs.
+     * @return The FileObject.
+     * @since 2.0
      */
-    @Override
-    public void fileChanged(final FileChangeEvent event) throws Exception {
-        if (event.getFileObject() != file) {
-            return;
-        }
-        if (!ignoreEvent) {
-            handleChanged();
-        }
+    public FileObject getDelegateFile() {
+        return file;
     }
 
     /**
-     * Close the delegated file.
+     * Checks whether the file's type has changed, and fires the appropriate events.
      *
-     * @throws FileSystemException if an error occurs.
+     * @param oldType The old FileType.
+     * @throws Exception if an error occurs.
      */
-    @Override
-    public void close() throws FileSystemException {
-        super.close();
-
-        if (file != null) {
-            file.close();
+    private void maybeTypeChanged(final FileType oldType) throws Exception {
+        final FileType newType = doGetType();
+        if (oldType == FileType.IMAGINARY && newType != FileType.IMAGINARY) {
+            handleCreate(newType);
+        } else if (oldType != FileType.IMAGINARY && newType == FileType.IMAGINARY) {
+            handleDelete();
         }
     }
 
@@ -375,45 +402,18 @@ public class DelegateFileObject<AFS extends AbstractFileSystem> extends Abstract
     }
 
     /**
-     * Return file content info.
-     *
-     * @return the file content info of the delegee.
-     * @throws Exception Any thrown Exception is wrapped in FileSystemException.
-     * @since 2.0
-     */
-    protected FileContentInfo doGetContentInfo() throws Exception {
-        return file.getContent().getContentInfo();
-    }
-
-    /**
-     * Renames the file.
-     *
-     * @param newFile the new location/name.
-     * @throws Exception Any thrown Exception is wrapped in FileSystemException.
-     * @since 2.0
-     */
-    @Override
-    protected void doRename(final FileObject newFile) throws Exception {
-        file.moveTo(((DelegateFileObject) newFile).file);
-    }
-
-    /**
-     * Removes an attribute of this file.
+     * Attaches or detaches the target file.
      *
-     * @since 2.0
+     * @param file The FileObject.
+     * @throws Exception if an error occurs.
      */
-    @Override
-    protected void doRemoveAttribute(final String atttrName) throws Exception {
-        file.getContent().removeAttribute(atttrName);
-    }
+    public void setFile(final FileObject file) throws Exception {
+        final FileType oldType = doGetType();
 
-    /**
-     * Creates access to the file for random i/o.
-     *
-     * @since 2.0
-     */
-    @Override
-    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
-        return file.getContent().getRandomAccessContent(mode);
+        if (file != null) {
+            WeakRefFileListener.installListener(file, this);
+        }
+        this.file = file;
+        maybeTypeChanged(oldType);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileContentThreadData.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileContentThreadData.java
index daf9283..3fc710d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileContentThreadData.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileContentThreadData.java
@@ -74,10 +74,6 @@ class FileContentThreadData {
         return hasInputStream() || outputStream != null || hasRandomAccessContent();
     }
 
-    InputStream removeInputStream(final int pos) {
-        return this.inputStreamList.remove(pos);
-    }
-
     void remove(final InputStream inputStream) {
         // this null-check (as well as the one in the other `remove` method) should not
         // be needed because `remove` is called only in `DefaultFileContent.endInput` which
@@ -94,16 +90,20 @@ class FileContentThreadData {
         }
     }
 
-    Object removeRandomAccessContent(final int pos) {
-        return this.randomAccessContentList.remove(pos);
-    }
-
     void remove(final RandomAccessContent randomAccessContent) {
         if (this.randomAccessContentList != null) {
             this.randomAccessContentList.remove(randomAccessContent);
         }
     }
 
+    InputStream removeInputStream(final int pos) {
+        return this.inputStreamList.remove(pos);
+    }
+
+    Object removeRandomAccessContent(final int pos) {
+        return this.randomAccessContentList.remove(pos);
+    }
+
     void setOutputStream(final DefaultFileContent.FileContentOutputStream outputStream) {
         this.outputStream = outputStream;
     }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileProvider.java
index 46edb27..0bc4ade 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/FileProvider.java
@@ -34,17 +34,6 @@ import org.apache.commons.vfs2.FileSystemOptions;
 public interface FileProvider {
 
     /**
-     * Locates a file object, by absolute URI.
-     *
-     * @param baseFile The base file to use for resolving the individual parts of a compound URI.
-     * @param uri The absolute URI of the file to find.
-     * @param fileSystemOptions The FileSystemOptions
-     * @return The FileObject.
-     * @throws FileSystemException if an error occurs locating the file.
-     */
-    FileObject findFile(FileObject baseFile, String uri, FileSystemOptions fileSystemOptions) throws FileSystemException;
-
-    /**
      * Creates a layered file system.
      *
      * @param scheme The URI scheme for the layered file system.
@@ -56,11 +45,15 @@ public interface FileProvider {
     FileObject createFileSystem(String scheme, FileObject file, FileSystemOptions fileSystemOptions) throws FileSystemException;
 
     /**
-     * Gets the configbuilder useable to collect the needed fileSystemOptions.
+     * Locates a file object, by absolute URI.
      *
-     * @return a FileSystemConfigBuilder for the particular file system.
+     * @param baseFile The base file to use for resolving the individual parts of a compound URI.
+     * @param uri The absolute URI of the file to find.
+     * @param fileSystemOptions The FileSystemOptions
+     * @return The FileObject.
+     * @throws FileSystemException if an error occurs locating the file.
      */
-    FileSystemConfigBuilder getConfigBuilder();
+    FileObject findFile(FileObject baseFile, String uri, FileSystemOptions fileSystemOptions) throws FileSystemException;
 
     /**
      * Gets the file system capabilities.
@@ -73,6 +66,13 @@ public interface FileProvider {
     Collection<Capability> getCapabilities();
 
     /**
+     * Gets the configbuilder useable to collect the needed fileSystemOptions.
+     *
+     * @return a FileSystemConfigBuilder for the particular file system.
+     */
+    FileSystemConfigBuilder getConfigBuilder();
+
+    /**
      * Parses the URI into a FileName.
      *
      * @param root The base FileName.
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
index a32da6c..12a5ebe 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericFileName.java
@@ -43,98 +43,98 @@ public class GenericFileName extends AbstractFileName {
     }
 
     /**
-     * Returns the user name part of this name.
+     * Append the user credentials.
+     * <p>
+     * If anything was added, it will be '@' terminated.
+     * </p>
      *
-     * @return The user name.
+     * @param buffer the string buffer to modify.
+     * @param addPassword flag if password should be added or replaced with placeholder (false).
      */
-    public String getUserName() {
-        return userName;
+    protected void appendCredentials(final StringBuilder buffer, final boolean addPassword) {
+        if (!StringUtils.isEmpty(userName)) {
+            UriParser.appendEncodedRfc2396(buffer, userName, RFC2396.USERINFO_UNESCAPED);
+            if (password != null && !password.isEmpty()) {
+                buffer.append(':');
+                if (addPassword) {
+                    UriParser.appendEncodedRfc2396(buffer, password, RFC2396.USERINFO_UNESCAPED);
+                } else {
+                    buffer.append("***");
+                }
+            }
+            buffer.append('@');
+        }
     }
 
     /**
-     * Returns the password part of this name.
-     *
-     * @return The password.
+     * Builds the root URI for this file name.
      */
-    public String getPassword() {
-        return password;
+    @Override
+    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
+        buffer.append(getScheme());
+        buffer.append("://");
+        appendCredentials(buffer, addPassword);
+        buffer.append(hostName);
+        if (port != getDefaultPort()) {
+            buffer.append(':');
+            buffer.append(port);
+        }
     }
 
     /**
-     * Returns the host name part of this name.
+     * Create a FileName.
      *
-     * @return The host name.
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The created FileName.
      */
-    public String getHostName() {
-        return hostName;
+    @Override
+    public FileName createName(final String absPath, final FileType type) {
+        return new GenericFileName(getScheme(), hostName, port, defaultPort, userName, password, absPath, type);
     }
 
     /**
-     * Returns the port part of this name.
+     * Returns the default port for this file name.
      *
-     * @return The port number.
+     * @return The default port number.
      */
-    public int getPort() {
-        return port;
+    public int getDefaultPort() {
+        return defaultPort;
     }
 
     /**
-     * Returns the default port for this file name.
+     * Returns the host name part of this name.
      *
-     * @return The default port number.
+     * @return The host name.
      */
-    public int getDefaultPort() {
-        return defaultPort;
+    public String getHostName() {
+        return hostName;
     }
 
     /**
-     * Create a FileName.
+     * Returns the password part of this name.
      *
-     * @param absPath The absolute path.
-     * @param type The FileType.
-     * @return The created FileName.
+     * @return The password.
      */
-    @Override
-    public FileName createName(final String absPath, final FileType type) {
-        return new GenericFileName(getScheme(), hostName, port, defaultPort, userName, password, absPath, type);
+    public String getPassword() {
+        return password;
     }
 
     /**
-     * Builds the root URI for this file name.
+     * Returns the port part of this name.
+     *
+     * @return The port number.
      */
-    @Override
-    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
-        buffer.append(getScheme());
-        buffer.append("://");
-        appendCredentials(buffer, addPassword);
-        buffer.append(hostName);
-        if (port != getDefaultPort()) {
-            buffer.append(':');
-            buffer.append(port);
-        }
+    public int getPort() {
+        return port;
     }
 
     /**
-     * Append the user credentials.
-     * <p>
-     * If anything was added, it will be '@' terminated.
-     * </p>
+     * Returns the user name part of this name.
      *
-     * @param buffer the string buffer to modify.
-     * @param addPassword flag if password should be added or replaced with placeholder (false).
+     * @return The user name.
      */
-    protected void appendCredentials(final StringBuilder buffer, final boolean addPassword) {
-        if (!StringUtils.isEmpty(userName)) {
-            UriParser.appendEncodedRfc2396(buffer, userName, RFC2396.USERINFO_UNESCAPED);
-            if (password != null && !password.isEmpty()) {
-                buffer.append(':');
-                if (addPassword) {
-                    UriParser.appendEncodedRfc2396(buffer, password, RFC2396.USERINFO_UNESCAPED);
-                } else {
-                    buffer.append("***");
-                }
-            }
-            buffer.append('@');
-        }
+    public String getUserName() {
+        return userName;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericURLFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericURLFileName.java
index 482244f..9a08f46 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericURLFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/GenericURLFileName.java
@@ -51,12 +51,35 @@ public class GenericURLFileName extends GenericFileName {
     }
 
     /**
-     * Gets the query string.
+     * Creates a FileName.
      *
-     * @return the query string part of the file name
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The FileName
      */
-    public String getQueryString() {
-        return queryString;
+    @Override
+    public FileName createName(final String absPath, final FileType type) {
+        return new GenericURLFileName(getScheme(), getHostName(), getPort(), getDefaultPort(), getUserName(), getPassword(),
+                absPath, type, getQueryString());
+    }
+
+    /**
+     * Appends query string to the uri.
+     *
+     * @return the uri
+     */
+    @Override
+    protected String createURI() {
+        if (getQueryString() != null) {
+            final StringBuilder sb = new StringBuilder(BUFFER_SIZE);
+            sb.append(super.createURI());
+            sb.append("?");
+            sb.append(getQueryString());
+
+            return sb.toString();
+        }
+
+        return super.createURI();
     }
 
     /**
@@ -100,35 +123,12 @@ public class GenericURLFileName extends GenericFileName {
     }
 
     /**
-     * Creates a FileName.
-     *
-     * @param absPath The absolute path.
-     * @param type The FileType.
-     * @return The FileName
-     */
-    @Override
-    public FileName createName(final String absPath, final FileType type) {
-        return new GenericURLFileName(getScheme(), getHostName(), getPort(), getDefaultPort(), getUserName(), getPassword(),
-                absPath, type, getQueryString());
-    }
-
-    /**
-     * Appends query string to the uri.
+     * Gets the query string.
      *
-     * @return the uri
+     * @return the query string part of the file name
      */
-    @Override
-    protected String createURI() {
-        if (getQueryString() != null) {
-            final StringBuilder sb = new StringBuilder(BUFFER_SIZE);
-            sb.append(super.createURI());
-            sb.append("?");
-            sb.append(getQueryString());
-
-            return sb.toString();
-        }
-
-        return super.createURI();
+    public String getQueryString() {
+        return queryString;
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileName.java
index b1dae5a..0b90d84 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileName.java
@@ -39,13 +39,12 @@ public class LayeredFileName extends AbstractFileName {
         this.outerUri = outerUri;
     }
 
-    /**
-     * Returns the URI of the outer file.
-     *
-     * @return The FileName.
-     */
-    public FileName getOuterName() {
-        return outerUri;
+    @Override
+    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
+        buffer.append(getScheme());
+        buffer.append(":");
+        buffer.append(getOuterName().getURI());
+        buffer.append("!");
     }
 
     /**
@@ -60,11 +59,12 @@ public class LayeredFileName extends AbstractFileName {
         return new LayeredFileName(getScheme(), getOuterName(), path, type);
     }
 
-    @Override
-    protected void appendRootUri(final StringBuilder buffer, final boolean addPassword) {
-        buffer.append(getScheme());
-        buffer.append(":");
-        buffer.append(getOuterName().getURI());
-        buffer.append("!");
+    /**
+     * Returns the URI of the outer file.
+     *
+     * @return The FileName.
+     */
+    public FileName getOuterName() {
+        return outerUri;
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileNameParser.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileNameParser.java
index 8647913..d5560c2 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileNameParser.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LayeredFileNameParser.java
@@ -50,6 +50,36 @@ public class LayeredFileNameParser extends AbstractFileNameParser {
     }
 
     /**
+     * Pops the root prefix off a URI, which has had the scheme removed.
+     *
+     * @param uri string builder which gets modified.
+     * @return the extracted root name.
+     */
+    protected String extractRootName(final StringBuilder uri) {
+        // Looking for <name>!<abspath> (staring at the end)
+        final int maxlen = uri.length();
+        int pos = maxlen - 1;
+        for (; pos > 0 && uri.charAt(pos) != '!'; pos--) {
+        }
+
+        if (pos == 0 && uri.charAt(pos) != '!') {
+            // not ! found, so take the whole path a root
+            // e.g. zip:/my/zip/file.zip
+            pos = maxlen;
+        }
+
+        // Extract the name
+        final String prefix = uri.substring(0, pos);
+        if (pos < maxlen) {
+            uri.delete(0, pos + 1);
+        } else {
+            uri.setLength(0);
+        }
+
+        return prefix;
+    }
+
+    /**
      * Parses the base and name into a FileName.
      *
      * @param context The component context.
@@ -82,34 +112,4 @@ public class LayeredFileNameParser extends AbstractFileNameParser {
         return new LayeredFileName(scheme, rootUri, path, fileType);
     }
 
-    /**
-     * Pops the root prefix off a URI, which has had the scheme removed.
-     *
-     * @param uri string builder which gets modified.
-     * @return the extracted root name.
-     */
-    protected String extractRootName(final StringBuilder uri) {
-        // Looking for <name>!<abspath> (staring at the end)
-        final int maxlen = uri.length();
-        int pos = maxlen - 1;
-        for (; pos > 0 && uri.charAt(pos) != '!'; pos--) {
-        }
-
-        if (pos == 0 && uri.charAt(pos) != '!') {
-            // not ! found, so take the whole path a root
-            // e.g. zip:/my/zip/file.zip
-            pos = maxlen;
-        }
-
-        // Extract the name
-        final String prefix = uri.substring(0, pos);
-        if (pos < maxlen) {
-            uri.delete(0, pos + 1);
-        } else {
-            uri.setLength(0);
-        }
-
-        return prefix;
-    }
-
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LocalFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LocalFileProvider.java
index 489083b..819b7c7 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LocalFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/LocalFileProvider.java
@@ -27,15 +27,13 @@ import org.apache.commons.vfs2.FileSystemException;
 public interface LocalFileProvider extends FileProvider {
 
     /**
-     * Determines if a name is an absolute file name.
-     * <p>
-     * TODO - Move this to a general file name parser interface.
-     * </p>
+     * Converts from java.io.File to FileObject.
      *
-     * @param name The name to test.
-     * @return true if the name is absolute.
+     * @param file The File for the file.
+     * @return The FileObject for the file.
+     * @throws FileSystemException if an error occurs.
      */
-    boolean isAbsoluteLocalName(String name);
+    FileObject findLocalFile(File file) throws FileSystemException;
 
     /**
      * Finds a local file, from its local name.
@@ -47,11 +45,13 @@ public interface LocalFileProvider extends FileProvider {
     FileObject findLocalFile(String name) throws FileSystemException;
 
     /**
-     * Converts from java.io.File to FileObject.
+     * Determines if a name is an absolute file name.
+     * <p>
+     * TODO - Move this to a general file name parser interface.
+     * </p>
      *
-     * @param file The File for the file.
-     * @return The FileObject for the file.
-     * @throws FileSystemException if an error occurs.
+     * @param name The name to test.
+     * @return true if the name is absolute.
      */
-    FileObject findLocalFile(File file) throws FileSystemException;
+    boolean isAbsoluteLocalName(String name);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/URLFileName.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/URLFileName.java
index 880e951..7511e49 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/URLFileName.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/URLFileName.java
@@ -54,12 +54,35 @@ public class URLFileName extends GenericFileName {
     }
 
     /**
-     * Gets the query string.
+     * Create a FileName.
      *
-     * @return the query string part of the file name
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The FileName
      */
-    public String getQueryString() {
-        return queryString;
+    @Override
+    public FileName createName(final String absPath, final FileType type) {
+        return new URLFileName(getScheme(), getHostName(), getPort(), getDefaultPort(), getUserName(), getPassword(),
+                absPath, type, getQueryString());
+    }
+
+    /**
+     * Appends query string to the URI.
+     *
+     * @return the URI
+     */
+    @Override
+    protected String createURI() {
+        if (getQueryString() != null) {
+            final StringBuilder sb = new StringBuilder(BUFFER_SIZE);
+            sb.append(super.createURI());
+            sb.append("?");
+            sb.append(getQueryString());
+
+            return sb.toString();
+        }
+
+        return super.createURI();
     }
 
     /**
@@ -104,35 +127,12 @@ public class URLFileName extends GenericFileName {
     }
 
     /**
-     * Create a FileName.
-     *
-     * @param absPath The absolute path.
-     * @param type The FileType.
-     * @return The FileName
-     */
-    @Override
-    public FileName createName(final String absPath, final FileType type) {
-        return new URLFileName(getScheme(), getHostName(), getPort(), getDefaultPort(), getUserName(), getPassword(),
-                absPath, type, getQueryString());
-    }
-
-    /**
-     * Appends query string to the URI.
+     * Gets the query string.
      *
-     * @return the URI
+     * @return the query string part of the file name
      */
-    @Override
-    protected String createURI() {
-        if (getQueryString() != null) {
-            final StringBuilder sb = new StringBuilder(BUFFER_SIZE);
-            sb.append(super.createURI());
-            sb.append("?");
-            sb.append(getQueryString());
-
-            return sb.toString();
-        }
-
-        return super.createURI();
+    public String getQueryString() {
+        return queryString;
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponent.java
index ed6f86b..18fbd2d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponent.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponent.java
@@ -34,11 +34,17 @@ import org.apache.commons.vfs2.FileSystemException;
 public interface VfsComponent extends Closeable {
 
     /**
-     * Sets the Logger to use for the component.
+     * Closes the component.
+     */
+    @Override
+    void close();
+
+    /**
+     * Initializes the component.
      *
-     * @param logger The Log
+     * @throws FileSystemException if an error occurs.
      */
-    void setLogger(Log logger);
+    void init() throws FileSystemException;
 
     /**
      * Sets the context for the component.
@@ -48,15 +54,9 @@ public interface VfsComponent extends Closeable {
     void setContext(VfsComponentContext context);
 
     /**
-     * Initializes the component.
+     * Sets the Logger to use for the component.
      *
-     * @throws FileSystemException if an error occurs.
-     */
-    void init() throws FileSystemException;
-
-    /**
-     * Closes the component.
+     * @param logger The Log
      */
-    @Override
-    void close();
+    void setLogger(Log logger);
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponentContext.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponentContext.java
index 4ea0608..aa6d416 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponentContext.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/VfsComponentContext.java
@@ -33,27 +33,27 @@ import org.apache.commons.vfs2.FileSystemOptions;
 public interface VfsComponentContext {
 
     /**
-     * Resolves a file by name. See {@link FileSystemManager#resolveFile(FileObject, String)} for a description of how
-     * this works.
+     * Gets the file system manager for the current context.
      *
-     * @param baseFile The base FileObject.
-     * @param name The name of the file to locate.
-     * @param fileSystemOptions The FileSystemOptions.
-     * @return The FileObject for the located file.
+     * @return the file system manager
+     */
+    FileSystemManager getFileSystemManager();
+
+    /**
+     * Gets a file replicator for the provider to use.
+     *
+     * @return The FileReplicator.
      * @throws FileSystemException if an error occurs.
      */
-    FileObject resolveFile(FileObject baseFile, String name, FileSystemOptions fileSystemOptions)
-            throws FileSystemException;
+    FileReplicator getReplicator() throws FileSystemException;
 
     /**
-     * Resolves a file by name. See {@link FileSystemManager#resolveFile( String)} for a description of how this works.
+     * Gets a temporary file store for the provider to use.
      *
-     * @param name The name of the file to locate.
-     * @param fileSystemOptions The FileSystemOptions.
-     * @return The FileObject for the located file.
+     * @return The TemporaryFileStore.
      * @throws FileSystemException if an error occurs.
      */
-    FileObject resolveFile(String name, FileSystemOptions fileSystemOptions) throws FileSystemException;
+    TemporaryFileStore getTemporaryFileStore() throws FileSystemException;
 
     /**
      * Parses a URI into a FileName.
@@ -65,20 +65,27 @@ public interface VfsComponentContext {
     FileName parseURI(String uri) throws FileSystemException;
 
     /**
-     * Gets a file replicator for the provider to use.
+     * Resolves a file by name. See {@link FileSystemManager#resolveFile(FileObject, String)} for a description of how
+     * this works.
      *
-     * @return The FileReplicator.
+     * @param baseFile The base FileObject.
+     * @param name The name of the file to locate.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return The FileObject for the located file.
      * @throws FileSystemException if an error occurs.
      */
-    FileReplicator getReplicator() throws FileSystemException;
+    FileObject resolveFile(FileObject baseFile, String name, FileSystemOptions fileSystemOptions)
+            throws FileSystemException;
 
     /**
-     * Gets a temporary file store for the provider to use.
+     * Resolves a file by name. See {@link FileSystemManager#resolveFile( String)} for a description of how this works.
      *
-     * @return The TemporaryFileStore.
+     * @param name The name of the file to locate.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return The FileObject for the located file.
      * @throws FileSystemException if an error occurs.
      */
-    TemporaryFileStore getTemporaryFileStore() throws FileSystemException;
+    FileObject resolveFile(String name, FileSystemOptions fileSystemOptions) throws FileSystemException;
 
     /**
      * Returns a {@link FileObject} for a local file.
@@ -88,11 +95,4 @@ public interface VfsComponentContext {
      * @throws FileSystemException if an error occurs.
      */
     FileObject toFileObject(File file) throws FileSystemException;
-
-    /**
-     * Gets the file system manager for the current context.
-     *
-     * @return the file system manager
-     */
-    FileSystemManager getFileSystemManager();
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileObject.java
index f7dfded..0d41ec3 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileObject.java
@@ -32,6 +32,10 @@ import org.apache.commons.vfs2.provider.compressed.CompressedFileFileSystem;
  */
 public class Bzip2FileObject extends CompressedFileFileObject<Bzip2FileSystem> {
 
+    protected Bzip2FileObject(final AbstractFileName name, final FileObject container, final Bzip2FileSystem fs) {
+        super(name, container, fs);
+    }
+
     /**
      * Deprecated since 2.1.
      *
@@ -47,14 +51,11 @@ public class Bzip2FileObject extends CompressedFileFileObject<Bzip2FileSystem> {
         super(name, container, cast(fs));
     }
 
-    protected Bzip2FileObject(final AbstractFileName name, final FileObject container, final Bzip2FileSystem fs) {
-        super(name, container, fs);
-    }
-
-    @Override
-    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
-        // check file
-        return wrapInputStream(getName().getURI(), getContainer().getContent().getInputStream(bufferSize));
+    private static Bzip2FileSystem cast(final CompressedFileFileSystem fs) {
+        if (fs instanceof Bzip2FileSystem) {
+            return (Bzip2FileSystem) fs;
+        }
+        throw new IllegalArgumentException("Bzip2FileObject requires a Bzip2FileSystem implementation");
     }
 
     /**
@@ -70,14 +71,13 @@ public class Bzip2FileObject extends CompressedFileFileObject<Bzip2FileSystem> {
     }
 
     @Override
-    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
-        return new BZip2CompressorOutputStream(getContainer().getContent().getOutputStream(false));
+    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
+        // check file
+        return wrapInputStream(getName().getURI(), getContainer().getContent().getInputStream(bufferSize));
     }
 
-    private static Bzip2FileSystem cast(final CompressedFileFileSystem fs) {
-        if (fs instanceof Bzip2FileSystem) {
-            return (Bzip2FileSystem) fs;
-        }
-        throw new IllegalArgumentException("Bzip2FileObject requires a Bzip2FileSystem implementation");
+    @Override
+    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
+        return new BZip2CompressorOutputStream(getContainer().getContent().getOutputStream(false));
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileSystem.java
index a07367c..df8b7e5 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/bzip2/Bzip2FileSystem.java
@@ -37,12 +37,12 @@ public class Bzip2FileSystem extends CompressedFileFileSystem {
     }
 
     @Override
-    protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
-        return new Bzip2FileObject(name, getParentLayer(), this);
+    protected void addCapabilities(final Collection<Capability> caps) {
+        caps.addAll(Bzip2FileProvider.capabilities);
     }
 
     @Override
-    protected void addCapabilities(final Collection<Capability> caps) {
-        caps.addAll(Bzip2FileProvider.capabilities);
+    protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
+        return new Bzip2FileObject(name, getParentLayer(), this);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java
index 77861f3..10507f8 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileObject.java
@@ -56,15 +56,27 @@ public abstract class CompressedFileFileObject<FS extends CompressedFileFileSyst
         children = new String[] {basename};
     }
 
+    @Override
+    public void createFile() throws FileSystemException {
+        container.createFile();
+        injectType(FileType.FILE);
+    }
+
     /**
-     * Determines if this file can be written to.
-     *
-     * @return {@code true} if this file is writable, {@code false} if not.
-     * @throws FileSystemException if an error occurs.
+     * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
+     * {@link FileType#FILE}.
      */
     @Override
-    public boolean isWriteable() throws FileSystemException {
-        return getFileSystem().hasCapability(Capability.WRITE_CONTENT);
+    protected long doGetContentSize() {
+        return SIZE_UNDEFINED;
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    @Override
+    protected long doGetLastModifiedTime() throws Exception {
+        return container.getContent().getLastModifiedTime();
     }
 
     /**
@@ -86,30 +98,18 @@ public abstract class CompressedFileFileObject<FS extends CompressedFileFileSyst
         return children;
     }
 
-    /**
-     * Returns the size of the file content (in bytes). Is only called if {@link #doGetType} returns
-     * {@link FileType#FILE}.
-     */
-    @Override
-    protected long doGetContentSize() {
-        return SIZE_UNDEFINED;
-    }
-
-    /**
-     * Returns the last modified time of this file.
-     */
-    @Override
-    protected long doGetLastModifiedTime() throws Exception {
-        return container.getContent().getLastModifiedTime();
-    }
-
     protected FileObject getContainer() {
         return container;
     }
 
+    /**
+     * Determines if this file can be written to.
+     *
+     * @return {@code true} if this file is writable, {@code false} if not.
+     * @throws FileSystemException if an error occurs.
+     */
     @Override
-    public void createFile() throws FileSystemException {
-        container.createFile();
-        injectType(FileType.FILE);
+    public boolean isWriteable() throws FileSystemException {
+        return getFileSystem().hasCapability(Capability.WRITE_CONTENT);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileProvider.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileProvider.java
index 1e3b2a3..dd77036 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileProvider.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/compressed/CompressedFileFileProvider.java
@@ -39,6 +39,8 @@ public abstract class CompressedFileFileProvider extends AbstractLayeredFileProv
     public CompressedFileFileProvider() {
     }
 
+    protected abstract FileSystem createFileSystem(FileName name, FileObject file, FileSystemOptions fileSystemOptions) throws FileSystemException;
+
     /**
      * Creates a layered file system. This method is called if the file system is not cached.
      *
@@ -53,8 +55,6 @@ public abstract class CompressedFileFileProvider extends AbstractLayeredFileProv
         return createFileSystem(name, file, fileSystemOptions);
     }
 
-    protected abstract FileSystem createFileSystem(FileName name, FileObject file, FileSystemOptions fileSystemOptions) throws FileSystemException;
-
     @Override
     public abstract Collection<Capability> getCapabilities();
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsClientFactory.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsClientFactory.java
index 8e5a63f..ee43f42 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsClientFactory.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsClientFactory.java
@@ -34,29 +34,6 @@ import org.apache.commons.vfs2.provider.ftp.FtpClientFactory;
  */
 public final class FtpsClientFactory {
 
-    private FtpsClientFactory() {
-        // empty
-    }
-
-    /**
-     * Creates a new connection to the server.
-     *
-     * @param hostname The host name.
-     * @param port The port.
-     * @param username The user name for authentication.
-     * @param password The user's password.
-     * @param workingDirectory The directory to use.
-     * @param fileSystemOptions The FileSystemOptions.
-     * @return The FTPSClient.
-     * @throws FileSystemException if an error occurs.
-     */
-    public static FTPSClient createConnection(final String hostname, final int port, final char[] username,
-            final char[] password, final String workingDirectory, final FileSystemOptions fileSystemOptions)
-            throws FileSystemException {
-        final FtpsConnectionFactory factory = new FtpsConnectionFactory(FtpsFileSystemConfigBuilder.getInstance());
-        return factory.createConnection(hostname, port, username, password, workingDirectory, fileSystemOptions);
-    }
-
     /** Connection Factory for FTPS case. */
     private static final class FtpsConnectionFactory
             extends FtpClientFactory.ConnectionFactory<FTPSClient, FtpsFileSystemConfigBuilder> {
@@ -96,4 +73,27 @@ public final class FtpsClientFactory {
             }
         }
     }
+
+    private FtpsClientFactory() {
+        // empty
+    }
+
+    /**
+     * Creates a new connection to the server.
+     *
+     * @param hostname The host name.
+     * @param port The port.
+     * @param username The user name for authentication.
+     * @param password The user's password.
+     * @param workingDirectory The directory to use.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return The FTPSClient.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static FTPSClient createConnection(final String hostname, final int port, final char[] username,
+            final char[] password, final String workingDirectory, final FileSystemOptions fileSystemOptions)
+            throws FileSystemException {
+        final FtpsConnectionFactory factory = new FtpsConnectionFactory(FtpsFileSystemConfigBuilder.getInstance());
+        return factory.createConnection(hostname, port, username, password, workingDirectory, fileSystemOptions);
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsFileSystemConfigBuilder.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsFileSystemConfigBuilder.java
index 814e667..8386f46 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsFileSystemConfigBuilder.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ftps/FtpsFileSystemConfigBuilder.java
@@ -53,21 +53,15 @@ public final class FtpsFileSystemConfigBuilder extends FtpFileSystemConfigBuilde
     }
 
     /**
-     * Sets FTPS mode, either "implicit" or "explicit".
-     *
-     * <p>
-     * Note, that implicit mode is not standardized and considered as deprecated. Some unit tests for VFS fail with
-     * implicit mode and it is not yet clear if its a problem with Commons VFS/Commons Net or our test server Apache
-     * FTP/SSHD.
-     * </p>
+     * Gets the data channel protection level (PROT).
      *
      * @param opts The FileSystemOptions.
-     * @param ftpsMode The mode to establish a FTPS connection.
-     * @see <a href="http://en.wikipedia.org/wiki/FTPS#Implicit">Wikipedia: FTPS/Implicit</a>
+     * @return The PROT value.
+     * @see org.apache.commons.net.ftp.FTPSClient#execPROT(String)
      * @since 2.1
      */
-    public void setFtpsMode(final FileSystemOptions opts, final FtpsMode ftpsMode) {
-        setParam(opts, FTPS_MODE, ftpsMode);
+    public FtpsDataChannelProtectionLevel getDataChannelProtectionLevel(final FileSystemOptions opts) {
+        return getEnum(FtpsDataChannelProtectionLevel.class, opts, PROT);
     }
 
     /**
@@ -82,33 +76,6 @@ public final class FtpsFileSystemConfigBuilder extends FtpFileSystemConfigBuilde
     }
 
     /**
-     * Sets FTPS type, either "implicit" or "explicit".
-     * <p>
-     * Note, that implicit mode is not standardized and considered as deprecated. Some unit tests for VFS fail with
-     * implicit mode and it is not yet clear if its a problem with Commons VFS/Commons Net or our test server Apache
-     * FTP/SSHD.
-     * </p>
-     *
-     * @param opts The FileSystemOptions.
-     * @param ftpsType The file type.
-     * @see <a href="http://en.wikipedia.org/wiki/FTPS#Implicit">Wikipedia: FTPS/Implicit</a>
-     * @deprecated As of 2.1, use {@link #setFtpsMode(FileSystemOptions, FtpsMode)}
-     */
-    @Deprecated
-    public void setFtpsType(final FileSystemOptions opts, final String ftpsType) {
-        final FtpsMode mode;
-        if (ftpsType != null) {
-            mode = FtpsMode.valueOf(ftpsType.toUpperCase());
-            if (mode == null) {
-                throw new IllegalArgumentException("Not a proper FTPS mode: " + ftpsType);
-            }
-        } else {
-            mode = null;
-        }
-        setFtpsMode(opts, mode);
-    }
-
-    /**
      * Returns the FTPS type. Defaults to "explicit" if not defined.
      *
      * @param opts The FileSystemOptions.
@@ -122,15 +89,37 @@ public final class FtpsFileSystemConfigBuilder extends FtpFileSystemConfigBuilde
     }
 
     /**
-     * Gets the data channel protection level (PROT).
+     * Gets the KeyManager used to provide a client-side certificate if the FTPS server requests it.
      *
      * @param opts The FileSystemOptions.
-     * @return The PROT value.
-     * @see org.apache.commons.net.ftp.FTPSClient#execPROT(String)
+     * @return the key manager instance or {@code null}
+     * @see org.apache.commons.net.ftp.FTPSClient#setKeyManager(KeyManager)
      * @since 2.1
      */
-    public FtpsDataChannelProtectionLevel getDataChannelProtectionLevel(final FileSystemOptions opts) {
-        return getEnum(FtpsDataChannelProtectionLevel.class, opts, PROT);
+    public KeyManager getKeyManager(final FileSystemOptions opts) {
+        return getParam(opts, KEY_MANAGER);
+    }
+
+    /**
+     * Gets the TrustManager that validates the FTPS server's certificate.
+     * <p>
+     * If the params do not contain the key for the trust manager, it will return a trust manger that simply checks this
+     * certificate for validity.
+     * </p>
+     *
+     * @param opts The FileSystemOptions.
+     * @return the trust manager instance or {@code null}
+     * @see org.apache.commons.net.ftp.FTPSClient#setTrustManager(TrustManager)
+     * @since 2.1
+     */
+    public TrustManager getTrustManager(final FileSystemOptions opts) {
+        final TrustManager trustManager;
+        if (hasParam(opts, TRUST_MANAGER)) {
+            trustManager = getParam(opts, TRUST_MANAGER);
+        } else {
+            trustManager = TrustManagerUtils.getValidateServerCertificateTrustManager();
+        }
+        return trustManager;
     }
 
     /**
@@ -146,49 +135,60 @@ public final class FtpsFileSystemConfigBuilder extends FtpFileSystemConfigBuilde
     }
 
     /**
-     * Gets the KeyManager used to provide a client-side certificate if the FTPS server requests it.
+     * Sets FTPS mode, either "implicit" or "explicit".
+     *
+     * <p>
+     * Note, that implicit mode is not standardized and considered as deprecated. Some unit tests for VFS fail with
+     * implicit mode and it is not yet clear if its a problem with Commons VFS/Commons Net or our test server Apache
+     * FTP/SSHD.
+     * </p>
      *
      * @param opts The FileSystemOptions.
-     * @return the key manager instance or {@code null}
-     * @see org.apache.commons.net.ftp.FTPSClient#setKeyManager(KeyManager)
+     * @param ftpsMode The mode to establish a FTPS connection.
+     * @see <a href="http://en.wikipedia.org/wiki/FTPS#Implicit">Wikipedia: FTPS/Implicit</a>
      * @since 2.1
      */
-    public KeyManager getKeyManager(final FileSystemOptions opts) {
-        return getParam(opts, KEY_MANAGER);
+    public void setFtpsMode(final FileSystemOptions opts, final FtpsMode ftpsMode) {
+        setParam(opts, FTPS_MODE, ftpsMode);
     }
 
     /**
-     * Sets the KeyManager used to provide a client-side certificate if the FTPS server requests it.
+     * Sets FTPS type, either "implicit" or "explicit".
+     * <p>
+     * Note, that implicit mode is not standardized and considered as deprecated. Some unit tests for VFS fail with
+     * implicit mode and it is not yet clear if its a problem with Commons VFS/Commons Net or our test server Apache
+     * FTP/SSHD.
+     * </p>
      *
      * @param opts The FileSystemOptions.
-     * @param keyManager The key manager instance.
-     * @see org.apache.commons.net.ftp.FTPSClient#setKeyManager(KeyManager)
-     * @since 2.1
+     * @param ftpsType The file type.
+     * @see <a href="http://en.wikipedia.org/wiki/FTPS#Implicit">Wikipedia: FTPS/Implicit</a>
+     * @deprecated As of 2.1, use {@link #setFtpsMode(FileSystemOptions, FtpsMode)}
      */
-    public void setKeyManager(final FileSystemOptions opts, final KeyManager keyManager) {
-        setParam(opts, KEY_MANAGER, keyManager);
+    @Deprecated
+    public void setFtpsType(final FileSystemOptions opts, final String ftpsType) {
+        final FtpsMode mode;
+        if (ftpsType != null) {
+            mode = FtpsMode.valueOf(ftpsType.toUpperCase());
+            if (mode == null) {
+                throw new IllegalArgumentException("Not a proper FTPS mode: " + ftpsType);
+            }
+        } else {
+            mode = null;
+        }
+        setFtpsMode(opts, mode);
     }
 
     /**
-     * Gets the TrustManager that validates the FTPS server's certificate.
-     * <p>
-     * If the params do not contain the key for the trust manager, it will return a trust manger that simply checks this
-     * certificate for validity.
-     * </p>
+     * Sets the KeyManager used to provide a client-side certificate if the FTPS server requests it.
      *
      * @param opts The FileSystemOptions.
-     * @return the trust manager instance or {@code null}
-     * @see org.apache.commons.net.ftp.FTPSClient#setTrustManager(TrustManager)
+     * @param keyManager The key manager instance.
+     * @see org.apache.commons.net.ftp.FTPSClient#setKeyManager(KeyManager)
      * @since 2.1
      */
-    public TrustManager getTrustManager(final FileSystemOptions opts) {
-        final TrustManager trustManager;
-        if (hasParam(opts, TRUST_MANAGER)) {
-            trustManager = getParam(opts, TRUST_MANAGER);
-        } else {
-            trustManager = TrustManagerUtils.getValidateServerCertificateTrustManager();
-        }
-        return trustManager;
+    public void setKeyManager(final FileSystemOptions opts, final KeyManager keyManager) {
+        setParam(opts, KEY_MANAGER, keyManager);
     }
 
     /**
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileObject.java
index 79906be..f087a2c 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileObject.java
@@ -50,6 +50,13 @@ public class GzipFileObject extends CompressedFileFileObject<GzipFileSystem> {
         super(name, container, fs);
     }
 
+    private static GzipFileSystem cast(final CompressedFileFileSystem fs) {
+        if (fs instanceof GzipFileSystem) {
+            return (GzipFileSystem) fs;
+        }
+        throw new IllegalArgumentException("GzipFileObject expects an instance of GzipFileSystem");
+    }
+
     @Override
     protected InputStream doGetInputStream(final int bufferSize) throws Exception {
         return new GZIPInputStream(getContainer().getContent().getInputStream(), bufferSize);
@@ -59,11 +66,4 @@ public class GzipFileObject extends CompressedFileFileObject<GzipFileSystem> {
     protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
         return new GZIPOutputStream(getContainer().getContent().getOutputStream(false));
     }
-
-    private static GzipFileSystem cast(final CompressedFileFileSystem fs) {
-        if (fs instanceof GzipFileSystem) {
-            return (GzipFileSystem) fs;
-        }
-        throw new IllegalArgumentException("GzipFileObject expects an instance of GzipFileSystem");
-    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileSystem.java
index aa4edf6..813cec5 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/gzip/GzipFileSystem.java
@@ -37,12 +37,12 @@ public class GzipFileSystem extends CompressedFileFileSystem {
     }
 
     @Override
-    protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
-        return new GzipFileObject(name, getParentLayer(), this);
+    protected void addCapabilities(final Collection<Capability> caps) {
+        caps.addAll(GzipFileProvider.capabilities);
     }
 
     @Override
-    protected void addCapabilities(final Collection<Capability> caps) {
-        caps.addAll(GzipFileProvider.capabilities);
+    protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
+        return new GzipFileObject(name, getParentLayer(), this);
     }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileObject.java
index 2cdb6cb..0435856 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileObject.java
@@ -59,32 +59,14 @@ public class JarFileObject extends ZipFileObject {
     }
 
     /**
-     * Returns the Jar manifest.
-     */
-    Manifest getManifest() throws IOException {
-        if (fs.getZipFile() == null) {
-            return null;
-        }
-
-        return ((JarFile) fs.getZipFile()).getManifest();
-    }
-
-    /**
-     * Returns the attributes of this file.
+     * Adds the source attributes to the destination map.
      */
-    Attributes getAttributes() throws IOException {
-        if (attributes == null) {
-            if (entry == null) {
-                attributes = new Attributes(1);
-            } else {
-                attributes = ((JarEntry) entry).getAttributes();
-                if (attributes == null) {
-                    attributes = new Attributes(1);
-                }
-            }
+    private void addAll(final Attributes src, final Map<String, Object> dest) {
+        for (final Entry<Object, Object> entry : src.entrySet()) {
+            // final String name = entry.getKey().toString().toLowerCase();
+            final String name = entry.getKey().toString();
+            dest.put(name, entry.getValue());
         }
-
-        return attributes;
     }
 
     /**
@@ -105,17 +87,6 @@ public class JarFileObject extends ZipFileObject {
     }
 
     /**
-     * Adds the source attributes to the destination map.
-     */
-    private void addAll(final Attributes src, final Map<String, Object> dest) {
-        for (final Entry<Object, Object> entry : src.entrySet()) {
-            // final String name = entry.getKey().toString().toLowerCase();
-            final String name = entry.getKey().toString();
-            dest.put(name, entry.getValue());
-        }
-    }
-
-    /**
      * Return the certificates of this JarEntry.
      */
     @Override
@@ -126,4 +97,33 @@ public class JarFileObject extends ZipFileObject {
 
         return ((JarEntry) entry).getCertificates();
     }
+
+    /**
+     * Returns the attributes of this file.
+     */
+    Attributes getAttributes() throws IOException {
+        if (attributes == null) {
+            if (entry == null) {
+                attributes = new Attributes(1);
+            } else {
+                attributes = ((JarEntry) entry).getAttributes();
+                if (attributes == null) {
+                    attributes = new Attributes(1);
+                }
+            }
+        }
+
+        return attributes;
+    }
+
+    /**
+     * Returns the Jar manifest.
+     */
+    Manifest getManifest() throws IOException {
+        if (fs.getZipFile() == null) {
+            return null;
+        }
+
+        return ((JarFile) fs.getZipFile()).getManifest();
+    }
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileSystem.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileSystem.java
index f2cb974..3d29b1d 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileSystem.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarFileSystem.java
@@ -51,6 +51,15 @@ public class JarFileSystem extends ZipFileSystem {
     // return new JarFileObject(name, null, this, false);
     // }
 
+    /**
+     * Returns the capabilities of this file system.
+     */
+    @Override
+    protected void addCapabilities(final Collection<Capability> caps) {
+        // super.addCapabilities(caps);
+        caps.addAll(JarFileProvider.CAPABILITIES);
+    }
+
     @Override
     protected ZipFile createZipFile(final File file) throws FileSystemException {
         try {
@@ -66,13 +75,26 @@ public class JarFileSystem extends ZipFileSystem {
         return new JarFileObject(name, entry, this, true);
     }
 
+    Object getAttribute(final Name attrName) throws FileSystemException {
+        try {
+            final Attributes attr = getAttributes();
+            return attr.getValue(attrName);
+        } catch (final IOException ioe) {
+            throw new FileSystemException(attrName.toString(), ioe);
+        }
+    }
+
     /**
-     * Returns the capabilities of this file system.
+     * Retrives the attribute with the specified name. The default implementation simply throws an exception.
+     *
+     * @param attrName The attiribute's name.
+     * @return The value of the attribute.
+     * @throws FileSystemException if an error occurs.
      */
     @Override
-    protected void addCapabilities(final Collection<Capability> caps) {
-        // super.addCapabilities(caps);
-        caps.addAll(JarFileProvider.CAPABILITIES);
+    public Object getAttribute(final String attrName) throws FileSystemException {
+        final Name name = lookupName(attrName);
+        return getAttribute(name);
     }
 
     Attributes getAttributes() throws IOException {
@@ -91,13 +113,10 @@ public class JarFileSystem extends ZipFileSystem {
         return attributes;
     }
 
-    Object getAttribute(final Name attrName) throws FileSystemException {
-        try {
-            final Attributes attr = getAttributes();
-            return attr.getValue(attrName);
-        } catch (final IOException ioe) {
-            throw new FileSystemException(attrName.toString(), ioe);
-        }
+    @Override
+    protected ZipFile getZipFile() throws FileSystemException {
+        // make accessible
+        return super.getZipFile();
     }
 
     Name lookupName(final String attrName) {
@@ -155,23 +174,4 @@ public class JarFileSystem extends ZipFileSystem {
         return new Name(attrName);
     }
 
-    /**
-     * Retrives the attribute with the specified name. The default implementation simply throws an exception.
-     *
-     * @param attrName The attiribute's name.
-     * @return The value of the attribute.
-     * @throws FileSystemException if an error occurs.
-     */
-    @Override
-    public Object getAttribute(final String attrName) throws FileSystemException {
-        final Name name = lookupName(attrName);
-        return getAttribute(name);
-    }
-
-    @Override
-    protected ZipFile getZipFile() throws FileSystemException {
-        // make accessible
-        return super.getZipFile();
-    }
-
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarURLConnectionImpl.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarURLConnectionImpl.java
index 4fe5b0e..691d342 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarURLConnectionImpl.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/jar/JarURLConnectionImpl.java
@@ -64,62 +64,62 @@ public class JarURLConnectionImpl extends JarURLConnection {
     }
 
     @Override
-    public URL getJarFileURL() {
-        return parentURL;
+    public void connect() {
+        connected = true;
     }
 
     @Override
-    public String getEntryName() {
-        return entryName;
+    public Attributes getAttributes() throws IOException {
+        return jarFileObject.getAttributes();
     }
 
     @Override
-    public JarFile getJarFile() throws IOException {
-        throw new FileSystemException("vfs.provider.jar/jar-file-no-access.error");
+    public Certificate[] getCertificates() {
+        return jarFileObject.doGetCertificates();
     }
 
     @Override
-    public Manifest getManifest() throws IOException {
-        return jarFileObject.getManifest();
+    public int getContentLength() {
+        try {
+            return (int) fileContent.getSize();
+        } catch (final FileSystemException ignored) {
+            return -1;
+        }
     }
 
     @Override
-    public JarEntry getJarEntry() throws IOException {
-        throw new FileSystemException("vfs.provider.jar/jar-entry-no-access.error");
+    public String getEntryName() {
+        return entryName;
     }
 
     @Override
-    public Attributes getAttributes() throws IOException {
-        return jarFileObject.getAttributes();
+    public InputStream getInputStream() throws IOException {
+        return fileContent.getInputStream();
     }
 
     @Override
-    public Certificate[] getCertificates() {
-        return jarFileObject.doGetCertificates();
+    public JarEntry getJarEntry() throws IOException {
+        throw new FileSystemException("vfs.provider.jar/jar-entry-no-access.error");
     }
 
     @Override
-    public void connect() {
-        connected = true;
+    public JarFile getJarFile() throws IOException {
+        throw new FileSystemException("vfs.provider.jar/jar-file-no-access.error");
     }
 
     @Override
-    public InputStream getInputStream() throws IOException {
-        return fileContent.getInputStream();
+    public URL getJarFileURL() {
+        return parentURL;
     }
 
     @Override
-    public OutputStream getOutputStream() throws IOException {
-        return fileContent.getOutputStream();
+    public Manifest getManifest() throws IOException {
+        return jarFileObject.getManifest();
     }
 
     @Override
-    public int getContentLength() {
-        try {
-            return (int) fileContent.getSize();
-        } catch (final FileSystemException ignored) {
-            return -1;
-        }
+    public OutputStream getOutputStream() throws IOException {
+        return fileContent.getOutputStream();
     }
 
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileData.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileData.java
index 5bd5e14..aa3cd6e 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileData.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileData.java
@@ -76,60 +76,75 @@ final class RamFileData implements Serializable {
     }
 
     /**
-     * @return Returns the buffer.
+     * Add a child.
+     *
+     * @param data The file data.
+     * @throws FileSystemException if an error occurs.
      */
-    byte[] getContent() {
-        return content;
-    }
+    void addChild(final RamFileData data) throws FileSystemException {
+        if (!this.getType().hasChildren()) {
+            throw new FileSystemException("A child can only be added in a folder");
+        }
 
-    /**
-     * @param content The buffer.
-     */
-    void setContent(final byte[] content) {
+        FileSystemException.requireNonNull(data, "No child can be null");
+
+        if (this.children.contains(data)) {
+            throw new FileSystemException("Child already exists. " + data);
+        }
+
+        this.children.add(data);
         updateLastModified();
-        this.content = content;
     }
 
     /**
-     * @return Returns the lastModified.
      */
-    long getLastModified() {
-        return lastModifiedMillis;
+    void clear() {
+        this.content = ArrayUtils.EMPTY_BYTE_ARRAY;
+        updateLastModified();
+        this.type = FileType.IMAGINARY;
+        this.children.clear();
+        this.name = null;
     }
 
-    /**
-     * @param lastModified The lastModified to set.
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
      */
-    void setLastModified(final long lastModified) {
-        this.lastModifiedMillis = lastModified;
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof RamFileData)) {
+            return false;
+        }
+        final RamFileData data = (RamFileData) o;
+        return this.getName().equals(data.getName());
     }
 
     /**
-     * @return Returns the type.
+     * @return Returns the children.
      */
-    FileType getType() {
-        return type;
+    Collection<RamFileData> getChildren() {
+        if (name == null) {
+            throw new IllegalStateException("Data is clear");
+        }
+        return children;
     }
 
     /**
-     * @param type The type to set.
+     * @return Returns the buffer.
      */
-    void setType(final FileType type) {
-        this.type = type;
+    byte[] getContent() {
+        return content;
     }
 
     /**
+     * @return Returns the lastModified.
      */
-    void clear() {
-        this.content = ArrayUtils.EMPTY_BYTE_ARRAY;
-        updateLastModified();
-        this.type = FileType.IMAGINARY;
-        this.children.clear();
-        this.name = null;
-    }
-
-    void updateLastModified() {
-        this.lastModifiedMillis = System.currentTimeMillis();
+    long getLastModified() {
+        return lastModifiedMillis;
     }
 
     /**
@@ -139,35 +154,25 @@ final class RamFileData implements Serializable {
         return name;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#toString()
+    /**
+     * @return Returns the type.
      */
-    @Override
-    public String toString() {
-        return this.name.toString();
+    FileType getType() {
+        return type;
     }
 
-    /**
-     * Add a child.
+    boolean hasChildren(final RamFileData data) {
+        return this.children.contains(data);
+    }
+
+    /*
+     * (non-Javadoc)
      *
-     * @param data The file data.
-     * @throws FileSystemException if an error occurs.
+     * @see java.lang.Object#hashCode()
      */
-    void addChild(final RamFileData data) throws FileSystemException {
-        if (!this.getType().hasChildren()) {
-            throw new FileSystemException("A child can only be added in a folder");
-        }
-
-        FileSystemException.requireNonNull(data, "No child can be null");
-
-        if (this.children.contains(data)) {
-            throw new FileSystemException("Child already exists. " + data);
-        }
-
-        this.children.add(data);
-        updateLastModified();
+    @Override
+    public int hashCode() {
+        return this.getName().hashCode();
     }
 
     /**
@@ -188,44 +193,44 @@ final class RamFileData implements Serializable {
     }
 
     /**
-     * @return Returns the children.
+     * Resize the buffer
+     *
+     * @param newSize The new buffer size.
      */
-    Collection<RamFileData> getChildren() {
-        if (name == null) {
-            throw new IllegalStateException("Data is clear");
+    void resize(final long newSize) {
+        // A future implementation may allow longs/multiple buffer/and so on
+        if (newSize > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException(
+                    String.format("newSize(%d) > Integer.MAX_VALUE(%d)", newSize, Integer.MAX_VALUE));
         }
-        return children;
+        final int resize = (int) newSize;
+        final int size = this.size();
+        final byte[] newBuf = new byte[resize];
+        System.arraycopy(this.content, 0, newBuf, 0, Math.min(resize, size));
+        this.content = newBuf;
+        updateLastModified();
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#equals(java.lang.Object)
+    /**
+     * @param content The buffer.
      */
-    @Override
-    public boolean equals(final Object o) {
-        if (this == o) {
-            return true;
-        }
-        if (!(o instanceof RamFileData)) {
-            return false;
-        }
-        final RamFileData data = (RamFileData) o;
-        return this.getName().equals(data.getName());
+    void setContent(final byte[] content) {
+        updateLastModified();
+        this.content = content;
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see java.lang.Object#hashCode()
+    /**
+     * @param lastModified The lastModified to set.
      */
-    @Override
-    public int hashCode() {
-        return this.getName().hashCode();
+    void setLastModified(final long lastModified) {
+        this.lastModifiedMillis = lastModified;
     }
 
-    boolean hasChildren(final RamFileData data) {
-        return this.children.contains(data);
+    /**
+     * @param type The type to set.
+     */
+    void setType(final FileType type) {
+        this.type = type;
     }
 
     /**
@@ -235,23 +240,18 @@ final class RamFileData implements Serializable {
         return content.length;
     }
 
-    /**
-     * Resize the buffer
+    /*
+     * (non-Javadoc)
      *
-     * @param newSize The new buffer size.
+     * @see java.lang.Object#toString()
      */
-    void resize(final long newSize) {
-        // A future implementation may allow longs/multiple buffer/and so on
-        if (newSize > Integer.MAX_VALUE) {
-            throw new IllegalArgumentException(
-                    String.format("newSize(%d) > Integer.MAX_VALUE(%d)", newSize, Integer.MAX_VALUE));
-        }
-        final int resize = (int) newSize;
-        final int size = this.size();
-        final byte[] newBuf = new byte[resize];
-        System.arraycopy(this.content, 0, newBuf, 0, Math.min(resize, size));
-        this.content = newBuf;
-        updateLastModified();
+    @Override
+    public String toString() {
+        return this.name.toString();
+    }
+
+    void updateLastModified() {
+        this.lastModifiedMillis = System.currentTimeMillis();
     }
 
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileObject.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileObject.java
index d730df5..51b01d4 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileObject.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileObject.java
@@ -52,28 +52,39 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
         this.getAbstractFileSystem().attach(this);
     }
 
-    private void save() throws FileSystemException {
-        this.getAbstractFileSystem().save(this);
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach()
+     */
+    @Override
+    protected void doAttach() throws Exception {
+        this.getAbstractFileSystem().attach(this);
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetType()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder()
      */
     @Override
-    protected FileType doGetType() throws Exception {
-        return data.getType();
+    protected void doCreateFolder() throws Exception {
+        this.injectType(FileType.FOLDER);
+        this.save();
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildren()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete()
      */
     @Override
-    protected String[] doListChildren() throws Exception {
-        return this.getAbstractFileSystem().listChildren(this.getName());
+    protected void doDelete() throws Exception {
+
+        if (this.isContentOpen()) {
+            throw new FileSystemException(this.getName() + " cannot be deleted while the file is openg");
+        }
+        getAbstractFileSystem().delete(this);
     }
 
     /*
@@ -104,61 +115,55 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetOutputStream(boolean)
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime()
      */
     @Override
-    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
-        if (!bAppend) {
-            this.data.setContent(ArrayUtils.EMPTY_BYTE_ARRAY);
-        }
-        return new RamFileOutputStream(this);
+    protected long doGetLastModifiedTime() throws Exception {
+        return data.getLastModified();
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doDelete()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetOutputStream(boolean)
      */
     @Override
-    protected void doDelete() throws Exception {
-
-        if (this.isContentOpen()) {
-            throw new FileSystemException(this.getName() + " cannot be deleted while the file is openg");
+    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
+        if (!bAppend) {
+            this.data.setContent(ArrayUtils.EMPTY_BYTE_ARRAY);
         }
-        getAbstractFileSystem().delete(this);
+        return new RamFileOutputStream(this);
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetRandomAccessContent(
+     * org.apache.commons.vfs2.util.RandomAccessMode)
      */
     @Override
-    protected long doGetLastModifiedTime() throws Exception {
-        return data.getLastModified();
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
+        return new RamFileRandomAccessContent(this, mode);
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetLastModifiedTime(long)
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetType()
      */
-    /** @since 2.0 */
     @Override
-    protected boolean doSetLastModifiedTime(final long modtime) throws Exception {
-        data.setLastModified(modtime);
-        return true;
+    protected FileType doGetType() throws Exception {
+        return data.getType();
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doCreateFolder()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doListChildren()
      */
     @Override
-    protected void doCreateFolder() throws Exception {
-        this.injectType(FileType.FOLDER);
-        this.save();
+    protected String[] doListChildren() throws Exception {
+        return this.getAbstractFileSystem().listChildren(this.getName());
     }
 
     /*
@@ -175,22 +180,24 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetRandomAccessContent(
-     * org.apache.commons.vfs2.util.RandomAccessMode)
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doSetLastModifiedTime(long)
      */
+    /** @since 2.0 */
     @Override
-    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
-        return new RamFileRandomAccessContent(this, mode);
+    protected boolean doSetLastModifiedTime(final long modtime) throws Exception {
+        data.setLastModified(modtime);
+        return true;
     }
 
     /*
      * (non-Javadoc)
      *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doAttach()
+     * @see org.apache.commons.vfs2.provider.AbstractFileObject#endOutput()
      */
     @Override
-    protected void doAttach() throws Exception {
-        this.getAbstractFileSystem().attach(this);
+    protected void endOutput() throws Exception {
+        super.endOutput();
+        this.save();
     }
 
     /**
@@ -200,13 +207,6 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
         return data;
     }
 
-    /**
-     * @param data The data to set.
-     */
-    void setData(final RamFileData data) {
-        this.data = data;
-    }
-
     /*
      * (non-Javadoc)
      *
@@ -218,24 +218,6 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
         super.injectType(fileType);
     }
 
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.commons.vfs2.provider.AbstractFileObject#endOutput()
-     */
-    @Override
-    protected void endOutput() throws Exception {
-        super.endOutput();
-        this.save();
-    }
-
-    /**
-     * @return Returns the size of the {@link RamFileData}.
-     */
-    int size() {
-        return data == null ? 0 : data.size();
-    }
-
     /**
      * @param newSize The new buffer size.
      * @throws IOException if the new size exceeds the limit
@@ -252,4 +234,22 @@ public class RamFileObject extends AbstractFileObject<RamFileSystem> {
         this.data.resize(newSize);
     }
 
+    private void save() throws FileSystemException {
+        this.getAbstractFileSystem().save(this);
+    }
+
+    /**
+     * @param data The data to set.
+     */
+    void setData(final RamFileData data) {
+        this.data = data;
+    }
+
+    /**
+     * @return Returns the size of the {@link RamFileData}.
+     */
+    int size() {
+        return data == null ? 0 : data.size();
+    }
+
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileOutputStream.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileOutputStream.java
index a8522da..ea23e7e 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileOutputStream.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileOutputStream.java
@@ -48,6 +48,28 @@ public class RamFileOutputStream extends OutputStream {
         this.file = file;
     }
 
+    @Override
+    public void close() throws IOException {
+        if (closed) {
+            return;
+        }
+        // Notify on close that there was an IOException while writing
+        if (exception != null) {
+            throw exception;
+        }
+        try {
+            this.closed = true;
+            // Close the
+            this.file.endOutput();
+        } catch (final Exception e) {
+            throw new FileSystemException(e);
+        }
+    }
+
+    @Override
+    public void flush() throws IOException {
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -79,26 +101,4 @@ public class RamFileOutputStream extends OutputStream {
         this.write(buffer1);
     }
 
-    @Override
-    public void flush() throws IOException {
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (closed) {
-            return;
-        }
-        // Notify on close that there was an IOException while writing
-        if (exception != null) {
-            throw exception;
-        }
-        try {
-            this.closed = true;
-            // Close the
-            this.file.endOutput();
-        } catch (final Exception e) {
-            throw new FileSystemException(e);
-        }
-    }
-
 }
diff --git a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileRandomAccessContent.java b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileRandomAccessContent.java
index 927585b..d6d571a 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileRandomAccessContent.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/ram/RamFileRandomAccessContent.java
@@ -33,6 +33,8 @@ import org.apache.commons.vfs2.util.RandomAccessMode;
  */
 public class RamFileRandomAccessContent implements RandomAccessContent {
 
+    private final static int BYTE_VALUE_MASK = 0xFF;
+
     /**
      * File Pointer
      */
@@ -70,8 +72,6 @@ public class RamFileRandomAccessContent implements RandomAccessContent {
 
     private final InputStream rafis;
 
-    private final static int BYTE_VALUE_MASK = 0xFF;
-
     /**
      * @param file The file to access.
      * @param mode The access mode.
@@ -84,22 +84,21 @@ public class RamFileRandomAccessContent implements RandomAccessContent {
 
         rafis = new InputStream() {
             @Override
-            public int read() throws IOException {
-                try {
-                    return readByte() & BYTE_VALUE_MASK;
-                } catch (final EOFException e) {
-                    return -1;
-                }
+            public int available() throws IOException {
+                return getLeftBytes();
             }
 
             @Override
-            public long skip(final long n) throws IOException {
-                seek(getFilePointer() + n);
-                return n;
+            public void close() throws IOException {
             }
 
             @Override
-            public void close() throws IOException {
+            public int read() throws IOException {
+                try {
+                    return readByte() & BYTE_VALUE_MASK;
... 4468 lines suppressed ...