Creating VFS-2.0-RC1 tag

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/vfs/tags/VFS-2.0-RC1@1030509 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/VFS-2.0-RC1/LICENSE.txt b/VFS-2.0-RC1/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/VFS-2.0-RC1/LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/VFS-2.0-RC1/NOTICE.txt b/VFS-2.0-RC1/NOTICE.txt
new file mode 100644
index 0000000..36b47ca
--- /dev/null
+++ b/VFS-2.0-RC1/NOTICE.txt
@@ -0,0 +1,10 @@
+Apache Commons VFS
+Copyright 2002-2010 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+As an optional dependency it uses javamail developed by
+SUN Microsystems
+You can get the library and its source from http://java.sun.com/products/javamail/
+This library uses the CDDL open source license 
diff --git a/VFS-2.0-RC1/checkstyle-header.txt b/VFS-2.0-RC1/checkstyle-header.txt
new file mode 100644
index 0000000..f974c9a
--- /dev/null
+++ b/VFS-2.0-RC1/checkstyle-header.txt
@@ -0,0 +1,16 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
\ No newline at end of file
diff --git a/VFS-2.0-RC1/checkstyle-suppressions.xml b/VFS-2.0-RC1/checkstyle-suppressions.xml
new file mode 100644
index 0000000..b44b9d8
--- /dev/null
+++ b/VFS-2.0-RC1/checkstyle-suppressions.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE suppressions PUBLIC
+    "-//Puppy Crawl//DTD Suppressions 1.0//EN"
+    "http://www.puppycrawl.com/dtds/suppressions_1_0.dtd">
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<!-- Exceptions for Checkstyle -->
+
+<suppressions>
+
+    <!-- Disable the warnings for the generated classes -->
+    <suppress checks=".*" files="ParseException.java"/>
+    <suppress checks=".*" files="PropertyListParser.java"/>
+    <suppress checks=".*" files="PropertyListParserConstants.java"/>
+    <suppress checks=".*" files="PropertyListParserTokenManager.java"/>
+    <suppress checks=".*" files="SimpleCharStream.java"/>
+    <suppress checks=".*" files="Token.java"/>
+    <suppress checks=".*" files="TokenMgrError.java"/>
+    
+    <suppress checks="MissingSwitchDefault" files="PropertiesConfiguration.java"/>
+
+</suppressions>
diff --git a/VFS-2.0-RC1/checkstyle.properties b/VFS-2.0-RC1/checkstyle.properties
new file mode 100644
index 0000000..5f82392
--- /dev/null
+++ b/VFS-2.0-RC1/checkstyle.properties
@@ -0,0 +1,25 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You under the Apache License, Version 2.0
+#   (the "License"); you may not use this file except in compliance with
+#   the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+checkstyle.maxlinelen = 120
+checkstyle.lcurly.type = nl
+checkstyle.lcurly.method = nl
+checkstyle.lcurly.other = nl
+checkstyle.rcurly = alone
+checkstyle.paren.pad = ignore
+checkstyle.ignore.whitespace.cast = true
+checkstyle.javadoc.scope = package
+checkstyle.require.packagehtml = true
+checkstyle.header.file = LICENSE.txt
diff --git a/VFS-2.0-RC1/checkstyle.xml b/VFS-2.0-RC1/checkstyle.xml
new file mode 100644
index 0000000..8c41f96
--- /dev/null
+++ b/VFS-2.0-RC1/checkstyle.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+    "-//Puppy Crawl//DTD Check Configuration 1.1//EN"
+    "http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<!-- Checkstyle configuration that checks the commons-configuration coding conventions -->
+
+<module name="Checker">
+    <property name="localeLanguage" value="en"/>
+
+    <!-- Checks that a package.html file exists for each package.     -->
+    <!-- See http://checkstyle.sf.net/config_javadoc.html#PackageHtml -->
+    <module name="PackageHtml"/>
+
+    <!-- Checks whether files end with a new line.                        -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
+    <module name="NewlineAtEndOfFile"/>
+
+    <!-- Checks that property files contain the same keys.         -->
+    <!-- See http://checkstyle.sf.net/config_misc.html#Translation -->
+    <module name="Translation"/>
+
+    <!-- Exceptions -->
+    <!--<module name="SuppressionFilter">
+        <property name="file" value="conf/checkstyle-suppressions.xml"/>
+    </module> -->
+
+    <module name="TreeWalker">
+
+        <property name="cacheFile" value="${checkstyle.cache.file}"/>
+
+        <!-- Checks for Javadoc comments.                     -->
+        <!-- See http://checkstyle.sf.net/config_javadoc.html -->
+        <module name="JavadocMethod">
+            <property name="scope" value="public"/>
+            <property name="allowUndeclaredRTE" value="true"/>
+              <property name="allowMissingJavadoc" value="true"/>
+        </module>
+        <module name="JavadocType">
+            <property name="authorFormat" value="\S"/>
+        </module>
+        <module name="JavadocVariable">
+            <property name="scope" value="protected"/>
+        </module>
+        <module name="JavadocStyle">
+            <property name="scope" value="public"/>
+        </module>
+
+
+        <!-- Checks for Naming Conventions.                  -->
+        <!-- See http://checkstyle.sf.net/config_naming.html -->
+        <module name="ConstantName"/>
+        <module name="LocalFinalVariableName"/>
+        <module name="LocalVariableName"/>
+        <module name="MemberName"/>
+        <module name="MethodName"/>
+        <module name="PackageName"/>
+        <module name="ParameterName"/>
+        <module name="StaticVariableName"/>
+        <module name="TypeName"/>
+
+
+        <!-- Checks for Headers                              -->
+        <!-- See http://checkstyle.sf.net/config_header.html -->
+        <module name="Header">
+            <property name="headerFile" value="${licensedir}"/>
+            <!--<property name="ignoreLines" value="2"/> -->
+        </module>
+
+        <!-- Following interprets the header file as regular expressions. -->
+        <!-- <module name="RegexpHeader"/>                                -->
+
+
+        <!-- Checks for imports                              -->
+        <!-- See http://checkstyle.sf.net/config_import.html -->
+        <module name="AvoidStarImport"/>
+        <module name="IllegalImport"/> <!-- defaults to sun.* packages -->
+        <module name="RedundantImport"/>
+        <module name="UnusedImports"/>
+
+
+        <!-- Checks for Size Violations.                    -->
+        <!-- See http://checkstyle.sf.net/config_sizes.html -->
+        <!--<module name="FileLength"/>-->
+        <module name="LineLength">
+            <property name="max" value="120"/>
+        </module>
+        <module name="MethodLength"/>
+        <module name="ParameterNumber">
+            <property name="max" value="10"/>
+        </module>
+
+
+        <!-- Checks for whitespace                               -->
+        <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+        <module name="EmptyForIteratorPad"/>
+        <module name="NoWhitespaceAfter"/>
+        <module name="NoWhitespaceBefore"/>
+        <module name="OperatorWrap">
+           <property name="tokens" value="ASSIGN"/>
+           <property name="option" value="eol"/>
+        </module>
+        <module name="ParenPad"/>
+        <module name="TabCharacter"/>
+        <module name="WhitespaceAfter"/>
+        <module name="WhitespaceAround"/>
+
+
+        <!-- Modifier Checks                                    -->
+        <!-- See http://checkstyle.sf.net/config_modifiers.html -->
+        <module name="ModifierOrder"/>
+        <module name="RedundantModifier"/>
+
+
+        <!-- Checks for blocks. You know, those {}'s         -->
+        <!-- See http://checkstyle.sf.net/config_blocks.html -->
+        <module name="AvoidNestedBlocks"/>
+        <!-- Require empty catch blocks to have at least a comment -->
+        <module name="EmptyBlock">
+          <property name="option" value="text"/>
+          <property name="tokens" value="LITERAL_CATCH"/>
+        </module>
+        <module name="LeftCurly">
+            <property name="option" value="nl"/>
+        </module>
+        <module name="NeedBraces"/>
+        <module name="RightCurly">
+            <property name="option" value="alone"/>
+        </module>
+
+
+        <!-- Checks for common coding problems               -->
+        <!-- See http://checkstyle.sf.net/config_coding.html -->
+        <module name="CovariantEquals"/>
+        <module name="DoubleCheckedLocking"/>
+        <module name="EqualsHashCode"/>
+        <module name="IllegalInstantiation"/>
+        <!-- <module name="InnerAssignment"/> -->
+        <module name="MagicNumber">
+            <property name="ignoreNumbers" value="-1,0,1,2,3"/>
+        </module>
+        <module name="RedundantThrows">
+            <property name="allowUnchecked" value="true"/>
+        </module>
+        <module name="SimplifyBooleanExpression"/>
+        <module name="SimplifyBooleanReturn"/>
+        <module name="StringLiteralEquality"/>
+        <module name="SuperClone"/>
+        <module name="SuperFinalize"/>
+        <module name="DeclarationOrder"/>
+        <!-- <module name="ExplicitInitialization"/> -->
+        <module name="DefaultComesLast"/>
+        <module name="FallThrough"/>
+        <module name="MultipleVariableDeclarations"/>
+        <!-- <module name="UnnecessaryParentheses"/> -->
+
+        <!-- Checks for class design                         -->
+        <!-- See http://checkstyle.sf.net/config_design.html -->
+        <module name="FinalClass"/>
+        <module name="HideUtilityClassConstructor"/>
+        <module name="InterfaceIsType"/>
+        <module name="VisibilityModifier">
+            <property name="protectedAllowed" value="true"/>
+        </module>
+
+
+
+        <!-- Miscellaneous other checks.                   -->
+        <!-- See http://checkstyle.sf.net/config_misc.html -->
+        <module name="ArrayTypeStyle"/>
+        <module name="GenericIllegalRegexp">
+            <property name="format" value="\s+$"/>
+            <property name="message" value="Line has trailing spaces."/>
+        </module>
+        <module name="TodoComment">
+            <property name="severity" value="info"/>
+        </module>
+        <module name="UpperEll"/>
+
+    </module>
+
+</module>
diff --git a/VFS-2.0-RC1/core/pom.xml b/VFS-2.0-RC1/core/pom.xml
new file mode 100644
index 0000000..37db107
--- /dev/null
+++ b/VFS-2.0-RC1/core/pom.xml
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Commons VFS Core</name>
+  <groupId>org.apache.commons</groupId>
+  <artifactId>commons-vfs</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <description>VFS is a Virtual File System library.</description>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-vfs-project</artifactId>
+    <version>2.0-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+
+  <dependencies>
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ant</groupId>
+      <artifactId>ant</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-net</groupId>
+      <artifactId>commons-net</artifactId>
+      <optional>true</optional>
+    </dependency>
+       <dependency>
+         <groupId>org.apache.commons</groupId>
+         <artifactId>commons-compress</artifactId>
+         <scope>test</scope>
+       </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-webdav</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>com.jcraft</groupId>
+      <artifactId>jsch</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>xml-apis</groupId>
+      <artifactId>xml-apis</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <vfs.parent.dir>${basedir}/..</vfs.parent.dir>
+  </properties>
+
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/java</directory>
+        <excludes>
+          <exclude>**/*.java</exclude>
+        </excludes>
+      </resource>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE.txt</include>
+        </includes>
+      </resource>
+    </resources>
+
+    <!-- include NOTICE/LICENSE in generated test jar -->
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+      </testResource>
+      <testResource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+        </includes>
+      </testResource>
+      <testResource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE.txt</include>
+        </includes>
+      </testResource>
+    </testResources>
+
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>process-test-classes</phase>
+            <configuration>
+              <tasks>
+                <move todir="${project.build.testOutputDirectory}/test-data/code"
+                      failonerror="false">
+                  <fileset dir="${project.build.testOutputDirectory}/code"/>
+                </move>
+
+              </tasks>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+
+      <plugin>
+        <!-- surfire do not honor suite(), see MSUREFIRE-131 why our tests wont work with maven 2 -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>test.basedir</name>
+              <value>target/test-classes/test-data</value>
+            </property>
+            <property>
+              <name>test.basedir.res</name>
+              <value>test-data</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>webdav</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-api</artifactId>
+          <version>1.5.6</version>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.slf4j</groupId>
+          <artifactId>slf4j-log4j12</artifactId>
+          <version>1.5.6</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>test.basedir</name>
+                  <value>target/test-classes/test-data</value>
+                </property>
+                <property>
+                  <name>test.basedir.res</name>
+                  <value>test-data</value>
+                </property>
+                <property>
+                  <name>test.webdav.uri</name>
+                  <value>${test.webdav.uri}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>ftp</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>test.basedir</name>
+                  <value>target/test-classes/test-data</value>
+                </property>
+                <property>
+                  <name>test.basedir.res</name>
+                  <value>test-data</value>
+                </property>
+                <property>
+                  <name>test.ftp.uri</name>
+                  <value>${test.ftp.uri}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>sftp</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>test.basedir</name>
+                  <value>target/test-classes/test-data</value>
+                </property>
+                <property>
+                  <name>test.basedir.res</name>
+                  <value>test-data</value>
+                </property>
+                <property>
+                  <name>test.sftp.uri</name>
+                  <value>${test.sftp.uri}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>http</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>test.basedir</name>
+                  <value>target/test-classes/test-data</value>
+                </property>
+                <property>
+                  <name>test.basedir.res</name>
+                  <value>test-data</value>
+                </property>
+                <property>
+                  <name>test.http.uri</name>
+                  <value>${test.http.uri}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/AllFileSelector.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/AllFileSelector.java
new file mode 100644
index 0000000..6fc698b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/AllFileSelector.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * A {@link FileSelector} that selects everything.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class AllFileSelector
+    implements FileSelector
+{
+    /**
+     * Determines if a file or folder should be selected.
+     * @param fileInfo The file selection information.
+     * @return true if the file should be selected, false otherwise.
+     */
+    public boolean includeFile(final FileSelectInfo fileInfo)
+    {
+        return true;
+    }
+
+    /**
+     * Determines whether a folder should be traversed.
+     * @param fileInfo The file selection information.
+     * @return true if descendents should be traversed, fase otherwise.
+     */
+    public boolean traverseDescendents(final FileSelectInfo fileInfo)
+    {
+        return true;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/CacheStrategy.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/CacheStrategy.java
new file mode 100644
index 0000000..a65621c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/CacheStrategy.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * An enumerated type to deal with the various cache strategies.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class CacheStrategy
+{
+    /**
+     * Deal with cached data manually. Call {@link FileObject#refresh()} to refresh the object data.
+     */
+    public static final CacheStrategy MANUAL = new CacheStrategy("manual");
+
+    /**
+     * Refresh the data every time you request a file from {@link FileSystemManager#resolveFile}.
+     */
+    public static final CacheStrategy ON_RESOLVE = new CacheStrategy("onresolve");
+
+    /**
+     * Refresh the data every time you call a method on the fileObject.
+     * You'll use this only if you really need the latest info as this setting is a major performance
+     * loss.
+     */
+    public static final CacheStrategy ON_CALL = new CacheStrategy("oncall");
+
+    /**
+     * Cache strategy name
+     */
+    private final String name;
+
+    private CacheStrategy(final String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * Returns the name of the scope.
+     * @return the name of the scope.
+     */
+    public String toString()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the name of the scope.
+     * @return the name of the scope.
+     */
+    public String getName()
+    {
+        return name;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Capability.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Capability.java
new file mode 100644
index 0000000..b5b9557
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Capability.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * An enumerated type representing the capabilities of files and file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class Capability
+{
+    /**
+     * File content can be read.
+     */
+    public static final Capability READ_CONTENT = new Capability("READ_CONTENT");
+
+    /**
+     * File content can be written.
+     */
+    public static final Capability WRITE_CONTENT = new Capability("WRITE_CONTENT");
+
+    /**
+     * File content can be read in random mode.<br>
+     */
+    public static final Capability RANDOM_ACCESS_READ = new Capability("RANDOM_ACCESS_READ");
+
+    /**
+     * File content can be written in random mode.<br>
+     */
+    public static final Capability RANDOM_ACCESS_WRITE = new Capability("RANDOM_ACCESS_WRITE");
+
+    /**
+     * File content can be appended.
+     */
+    public static final Capability APPEND_CONTENT = new Capability("APPEND_CONTENT");
+
+    /**
+     * File attributes are supported.
+     */
+    public static final Capability ATTRIBUTES = new Capability("ATTRIBUTES");
+
+    /**
+     * File last-modified time is supported.
+     */
+    public static final Capability LAST_MODIFIED = new Capability("LAST_MODIFIED");
+
+    /**
+     * File get last-modified time is supported.
+     */
+    public static final Capability GET_LAST_MODIFIED = new Capability("GET_LAST_MODIFIED");
+
+    /**
+     * File set last-modified time is supported.
+     */
+    public static final Capability SET_LAST_MODIFIED_FILE = new Capability("SET_LAST_MODIFIED_FILE");
+
+    /**
+     * folder set last-modified time is supported.
+     */
+    public static final Capability SET_LAST_MODIFIED_FOLDER = new Capability("SET_LAST_MODIFIED_FOLDER");
+
+    /**
+     * File content signing is supported.
+     */
+    public static final Capability SIGNING = new Capability("SIGNING");
+
+    /**
+     * Files can be created.
+     */
+    public static final Capability CREATE = new Capability("CREATE");
+
+    /**
+     * Files can be deleted.
+     */
+    public static final Capability DELETE = new Capability("DELETE");
+
+    /**
+     * Files can be renamed.
+     */
+    public static final Capability RENAME = new Capability("RENAME");
+
+    /**
+     * The file type can be determined.
+     */
+    public static final Capability GET_TYPE = new Capability("GET_TYPE");
+
+    /**
+     * Children of files can be listed.
+     */
+    public static final Capability LIST_CHILDREN = new Capability("LIST_CHILDREN");
+
+    /**
+     * URI are supported.  Files without this capability use URI that do not
+     * globally and uniquely identify the file.
+     */
+    public static final Capability URI = new Capability("URI");
+
+    /**
+     * File system attributes are supported.
+     */
+    public static final Capability FS_ATTRIBUTES = new Capability("FS_ATTRIBUTE");
+
+    /**
+     * Junctions are supported.
+     */
+    public static final Capability JUNCTIONS = new Capability("JUNCTIONS");
+
+    /**
+     * The set of attributes defined by the Jar manifest specification are
+     * supported.  The attributes aren't necessarily stored in a manifest file.
+     */
+    public static final Capability MANIFEST_ATTRIBUTES = new Capability("MANIFEST_ATTRIBUTES");
+
+    /**
+     * The provider itself do not provide a filesystem. It simply resolves a full name
+     * and dispatches the request back to the filesystemmanager.<br>
+     * A provider with this capability cant tell much about the capabilities about the
+     * finally used filesystem in advance.
+     */
+    public static final Capability DISPATCHER = new Capability("DISPATCHER");
+
+    /**
+     * A compressed filesystem is a filesystem which use compression.
+     */
+    public static final Capability COMPRESS = new Capability("COMPRESS");
+
+    /**
+     * A virtual filesystem can be an archive like tar or zip.
+     */
+    public static final Capability VIRTUAL = new Capability("VIRTUAL");
+
+    /**
+     * Provides directories which allows you to read its content through
+     * {@link org.apache.commons.vfs.FileContent#getInputStream()}.
+     */
+    public static final Capability DIRECTORY_READ_CONTENT = new Capability("DIRECTORY_READ_CONTENT");
+
+    /**
+     * The Capability name
+     */
+    private final String name;
+
+    private Capability(final String name)
+    {
+        this.name = name;
+    }
+
+    public String toString()
+    {
+        return name;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileChangeEvent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileChangeEvent.java
new file mode 100644
index 0000000..b7cfd23
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileChangeEvent.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * An event fired when a file is changed.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileChangeEvent
+{
+    /**
+     * The file object
+     */
+    private final FileObject file;
+
+    public FileChangeEvent(final FileObject file)
+    {
+        this.file = file;
+    }
+
+    /**
+     * Returns the file that changed.
+     * @return The FileObject that was changed.
+     */
+    public FileObject getFile()
+    {
+        return file;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContent.java
new file mode 100644
index 0000000..d5c7ee2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContent.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.util.Map;
+
+/**
+ * Represents the data content of a file.
+ * <p/>
+ * <p>To read from a file, use the <code>InputStream</code> returned by
+ * {@link #getInputStream}.
+ * <p/>
+ * <p>To write to a file, use the <code>OutputStream</code> returned by
+ * {@link #getOutputStream} method.  This will create the file, and the parent
+ * folder, if necessary.
+ * <p/>
+ * <p>A file may have multiple InputStreams open at the sametime.
+ * <p/>
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @see FileObject#getContent
+ */
+public interface FileContent
+{
+    /**
+     * Returns the file which this is the content of.
+     * @return The FileObject this is the content of.
+     */
+    FileObject getFile();
+
+    /**
+     * Determines the size of the file, in bytes.
+     *
+     * @return The size of the file, in bytes.
+     * @throws FileSystemException If the file does not exist, or is being written to, or on error
+     *                             determining the size.
+     */
+    long getSize() throws FileSystemException;
+
+    /**
+     * Determines the last-modified timestamp of the file.
+     *
+     * @return The last-modified timestamp.
+     * @throws FileSystemException If the file does not exist, or is being written to, or on error
+     *                             determining the last-modified timestamp.
+     */
+    long getLastModifiedTime() throws FileSystemException;
+
+    /**
+     * Sets the last-modified timestamp of the file.  Creates the file if
+     * it does not exist.
+     *
+     * @param modTime The time to set the last-modified timestamp to.
+     * @throws FileSystemException If the file is read-only, or is being written to, or on error
+     *                             setting the last-modified timestamp.
+     */
+    void setLastModifiedTime(long modTime) throws FileSystemException;
+
+    /**
+     * Checks if an attribute of the file's content exists.
+     *
+     * @param attrName The name of the attribute.
+     * @return true if the attribute exists, false otherwise.
+     * @throws FileSystemException If the file does not exist, or does not support
+     *                             attributes.
+     */
+    boolean hasAttribute(String attrName)
+        throws FileSystemException;
+
+    /**
+     * Returns a read-only map of this file's attributes.
+     * @return The attribute Map.
+     * @throws FileSystemException If the file does not exist, or does not support attributes.
+     */
+    Map getAttributes() throws FileSystemException;
+
+    /**
+     * Lists the attributes of the file's content.
+     *
+     * @return The names of the attributes.  Never returns null;
+     * @throws FileSystemException If the file does not exist, or does not support attributes.
+     */
+    String[] getAttributeNames() throws FileSystemException;
+
+    /**
+     * Gets the value of an attribute of the file's content.
+     *
+     * @param attrName The name of the attribute.  Attribute names are case insensitive.
+     * @return The value of the attribute, or null if the attribute value is
+     *         unknown.
+     * @throws FileSystemException If the file does not exist, or does not support attributes.
+     */
+    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.
+     *
+     * @param attrName The name of the attribute.
+     * @param value    The value of the attribute.
+     * @throws FileSystemException If the file does not exist, or is read-only, or does not support
+     *                             attributes, or on error setting the attribute.
+     */
+    void setAttribute(String attrName, Object value)
+        throws FileSystemException;
+
+    /**
+     * Removes the value of an attribute of the file's content.
+     *
+     * @param attrName The name of the attribute.
+     * @throws FileSystemException If the file does not exist, or is read-only, or does not support
+     *                             attributes, or on error removing the attribute.
+     */
+    void removeAttribute(String attrName)
+        throws FileSystemException;
+
+    /**
+     * Retrieves the certificates if any used to sign this file or folder.
+     *
+     * @return The certificates, or an empty array if there are no certificates or
+     *         the file does not support signing.
+     * @throws FileSystemException If the file does not exist, or is being written.
+     */
+    Certificate[] getCertificates() throws FileSystemException;
+
+    /**
+     * Returns an input stream for reading the file's content.
+     * <p/>
+     * <p>There may only be a single input or output stream open for the
+     * file at any time.
+     *
+     * @return An input stream to read the file's content from.  The input
+     *         stream is buffered, so there is no need to wrap it in a
+     *         <code>BufferedInputStream</code>.
+     * @throws FileSystemException If the file does not exist, or is being read, or is being written,
+     *                             or on error opening the stream.
+     */
+    InputStream getInputStream() throws FileSystemException;
+
+    /**
+     * Returns an output stream for writing the file's content.
+     * <p/>
+     * If the file does not exist, this method creates it, and the parent
+     * folder, if necessary.  If the file does exist, it is replaced with
+     * whatever is written to the output stream.
+     * <p/>
+     * <p>There may only be a single input or output stream open for the
+     * file at any time.
+     *
+     * @return An output stream to write the file's content to.  The stream is
+     *         buffered, so there is no need to wrap it in a
+     *         <code>BufferedOutputStream</code>.
+     * @throws FileSystemException If the file is read-only, or is being read, or is being written,
+     *                             or on error opening the stream.
+     */
+    OutputStream getOutputStream() throws FileSystemException;
+
+    /**
+     * Returns an stream for reading/writing the file's content.
+     * <p/>
+     * If the file does not exist, and you use one of the write* methods,
+     * this method creates it, and the parent folder, if necessary.
+     * If the file does exist, parts of the file are replaced with whatever is written
+     * at a given position.
+     * <p/>
+     * <p>There may only be a single input or output stream open for the
+     * file at any time.
+     *
+     * @param mode The mode to use to access the file.
+     * @return the stream for reading and writing the file's content.
+     * @throws FileSystemException If the file is read-only, or is being read, or is being written,
+     *                             or on error opening the stream.
+     */
+    RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException;
+
+    /**
+     * Returns an output stream for writing the file's content.
+     * <p/>
+     * If the file does not exist, this method creates it, and the parent
+     * folder, if necessary.  If the file does exist, it is replaced with
+     * whatever is written to the output stream.
+     * <p/>
+     * <p>There may only be a single input or output stream open for the
+     * file at any time.
+     *
+     * @param bAppend true if you would like to append to the file
+     * @return An output stream to write the file's content to.  The stream is
+     *         buffered, so there is no need to wrap it in a
+     *         <code>BufferedOutputStream</code>.
+     * @throws FileSystemException If the file is read-only, or is being read, or is being written,
+     *                             or on error opening the stream.
+     */
+    OutputStream getOutputStream(boolean bAppend) throws FileSystemException;
+
+    /**
+     * Closes all resources used by the content, including any open stream.
+     * Commits pending changes to the file.
+     * <p/>
+     * <p>This method is a hint to the implementation that it can release
+     * resources.  This object can continue to be used after calling this
+     * method.
+     * @throws FileSystemException if an error occurs closing the file.
+     */
+    void close() throws FileSystemException;
+
+    /**
+     * get the content info. e.g. type, encoding, ...
+     * @return the FileContentInfo
+     * @throws FileSystemException if an error occurs.
+     */
+    FileContentInfo getContentInfo() throws FileSystemException;
+
+    /**
+     * check if this file has open streams.
+     * @return true if the file is open, false otherwise.
+     */
+    boolean isOpen();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfo.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfo.java
new file mode 100644
index 0000000..c65e5fe
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Interface to the content info.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileContentInfo
+{
+    /**
+     * the content type.
+     * @return The file content type.
+     */
+    String getContentType();
+
+    /**
+     * the content encoding.
+     * @return The file content encoding.
+     */
+    String getContentEncoding();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfoFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfoFactory.java
new file mode 100644
index 0000000..8779016
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileContentInfoFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Create a class which is able to determine the content-info for the given content.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileContentInfoFactory
+{
+    FileContentInfo create(FileContent fileContent) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileDepthSelector.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileDepthSelector.java
new file mode 100644
index 0000000..fcaf299
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileDepthSelector.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * A {@link FileSelector} that selects all files in a particular depth range.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileDepthSelector
+    implements FileSelector
+{
+    /**
+     * The minimum depth
+     */
+    private final int minDepth;
+
+    /**
+     * The maximum depth
+     */
+    private final int maxDepth;
+
+    public FileDepthSelector(int minDepth, int maxDepth)
+    {
+        this.minDepth = minDepth;
+        this.maxDepth = maxDepth;
+    }
+
+    /**
+     * 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.
+     */
+    public boolean includeFile(final FileSelectInfo fileInfo)
+    {
+        final int depth = fileInfo.getDepth();
+        return minDepth <= depth && depth <= maxDepth;
+    }
+
+    /**
+     * Determines whether a folder should be traversed.
+     * @param fileInfo The file selection information
+     * @return true if the file or folder should be traversed, false otherwise.
+     */
+    public boolean traverseDescendents(final FileSelectInfo fileInfo)
+    {
+        return fileInfo.getDepth() < maxDepth;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilter.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilter.java
new file mode 100644
index 0000000..93c8a93
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilter.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * This interface is used to select files when traversing the direct children of the base.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public interface FileFilter
+{
+    /**
+     * Determines if a file or folder should be selected.
+     *
+     * @param fileInfo the file or folder to select.
+     * @return true if the file should be selected.
+     */
+    boolean accept(final FileSelectInfo fileInfo);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilterSelector.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilterSelector.java
new file mode 100644
index 0000000..a44cd2c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileFilterSelector.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import org.apache.commons.vfs.util.Messages;
+
+/**
+ * A {@link org.apache.commons.vfs.FileSelector} that selects all children of the given fileObject.<br />
+ * This is to mimic the {@link java.io.FileFilter} interface
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public class FileFilterSelector extends FileDepthSelector
+{
+    /**
+     * The FileFilter.
+     */
+    private final FileFilter fileFilter;
+
+    public FileFilterSelector()
+    {
+        this(null);
+    }
+
+    public FileFilterSelector(FileFilter fileFilter)
+    {
+        super(1, 1);
+        this.fileFilter = fileFilter;
+    }
+
+    /**
+     * 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.
+     */
+    public boolean includeFile(final FileSelectInfo fileInfo)
+    {
+        if (!super.includeFile(fileInfo))
+        {
+            return false;
+        }
+
+        return accept(fileInfo);
+    }
+
+    /**
+     * Determines whether the file should be selected.
+     * @param fileInfo The file selection information.
+     * @return true if the file should be selected, false otherwise.
+     */
+    public boolean accept(final FileSelectInfo fileInfo)
+    {
+        if (fileFilter != null)
+        {
+            return fileFilter.accept(fileInfo);
+        }
+
+        throw new IllegalArgumentException(Messages.getString("vfs.selectors/filefilter.missing.error"));
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileListener.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileListener.java
new file mode 100644
index 0000000..fb18ae0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileListener.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Listens for changes to a file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileListener
+{
+    /**
+     * Called when a file is created.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    void fileCreated(FileChangeEvent event) throws Exception;
+
+    /**
+     * Called when a file is deleted.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    void fileDeleted(FileChangeEvent event) throws Exception;
+
+    /**
+     * Called when a file is changed.<br />
+     * This will only happen if you monitor the file using {@link FileMonitor}.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    void fileChanged(FileChangeEvent event) throws Exception;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileMonitor.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileMonitor.java
new file mode 100644
index 0000000..9625ea0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileMonitor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * FileMonitor interface.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileMonitor
+{
+    /**
+     * Adds a file to be monitored.
+     * @param file The FileObject to monitor.
+     */
+    void addFile(final FileObject file);
+
+    /**
+     * Removes a file from being monitored.
+     * @param file The FileObject to stop monitoring.
+     */
+    void removeFile(final FileObject file);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileName.java
new file mode 100644
index 0000000..beba946
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileName.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Represents a file name.  File names are immutable, and work correctly as
+ * keys in hash tables.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @see FileObject
+ */
+public interface FileName extends Comparable
+{
+    /**
+     * The separator character used in file paths.
+     */
+    char SEPARATOR_CHAR = '/';
+
+    /**
+     * The separator used in file paths.
+     */
+    String SEPARATOR = "/";
+
+    /**
+     * The absolute path of the root of a file system.
+     */
+    String ROOT_PATH = "/";
+
+    /**
+     * Returns the base name of this file.  The base name is the last element
+     * of the file name.  For example the base name of
+     * <code>/somefolder/somefile</code> is <code>somefile</code>.
+     * <p/>
+     * <p>The root file of a file system has an empty base name.
+     *
+     * @return The base name.  Never returns null.
+     */
+    String getBaseName();
+
+    /**
+     * Returns the absolute path of this file, within its file system.  This
+     * path is normalised, so that <code>.</code> and <code>..</code> elements
+     * have been removed.  Also, the path only contains <code>/</code> as its
+     * separator character.  The path always starts with <code>/</code>
+     * <p/>
+     * <p>The root of a file system has <code>/</code> as its absolute path.
+     *
+     * @return The path.  Never returns null.
+     */
+    String getPath();
+
+    /**
+     * Returns the absolute path of this file, within its file system.  This
+     * path is normalised, so that <code>.</code> and <code>..</code> elements
+     * have been removed.  Also, the path only contains <code>/</code> as its
+     * separator character.  The path always starts with <code>/</code>
+     * <p/>
+     * <p>The root of a file system has <code>/</code> as its absolute path.
+     * <p/>
+     * In contrast to {@link #getPath()} the path is decoded i.e. all %nn stuff
+     * replaced by its character.
+     *
+     * @return The path.  Never returns null.
+     * @throws FileSystemException if the path is not correctly encoded
+     */
+    String getPathDecoded() throws FileSystemException;
+
+    /**
+     * Returns the extension of this file name.
+     *
+     * @return The extension.  Returns an empty string if the name has no
+     *         extension.
+     */
+    String getExtension();
+
+    /**
+     * Returns the depth of this file name, within its file system.  The depth
+     * of the root of a file system is 0.  The depth of any other file is
+     * 1 + the depth of its parent.
+     * @return The depth of this file name.
+     */
+    int getDepth();
+
+    /**
+     * Returns the URI scheme of this file.
+     * @return The URI scheme of this file.
+     */
+    String getScheme();
+
+    /**
+     * Returns the absolute URI of this file.
+     * @return the absolute URI of this file.
+     */
+    String getURI();
+
+    /**
+     * Returns the root URI of the file system this file belongs to.
+     * @return the root URI.
+     */
+    String getRootURI();
+
+    /**
+     * find the root of the filesystem.
+     * @return the file system root.
+     */
+    FileName getRoot();
+
+    /**
+     * Returns the file name of the parent of this file.  The root of a
+     * file system has no parent.
+     *
+     * @return A {@link FileName} object representing the parent name.  Returns
+     *         null for the root of a file system.
+     */
+    FileName getParent();
+
+    /**
+     * Resolves a name, relative to this file name.  Equivalent to calling
+     * <code>resolveName( path, NameScope.FILE_SYSTEM )</code>.
+     *
+     * @param name The name to resolve.
+     * @return A {@link FileName} object representing the resolved file name.
+     * @throws FileSystemException If the name is invalid.
+     */
+    // FileName resolveName(String name) throws FileSystemException;
+
+    /**
+     * Resolves a name, relative to this file name.  Refer to {@link NameScope}
+     * for a description of how names are resolved.
+     *
+     * @param name  The name to resolve.
+     * @param scope The scope to use when resolving the name.
+     * @return A {@link FileName} object representing the resolved file name.
+     * @throws FileSystemException If the name is invalid.
+     */
+    // FileName resolveName(String name, NameScope scope)
+    //     throws FileSystemException;
+
+    /**
+     * Converts a file name to a relative name, relative to this file name.
+     *
+     * @param name The name to convert to a relative path.
+     * @return The relative name.
+     * @throws FileSystemException On error.
+     */
+    String getRelativeName(FileName name) throws FileSystemException;
+
+    /**
+     * Determines if another file name is an ancestor of this file name.
+     * @param ancestor The FileName to check.
+     * @return true if another file name is an ancestor of this file name.
+     */
+    boolean isAncestor(FileName ancestor);
+
+    /**
+     * Determines if another file name is a descendent of this file name.
+     * @param descendent the FileName to check.
+     * @return true if the other FileName is a descendent of this file name.
+     */
+    boolean isDescendent(FileName descendent);
+
+    /**
+     * Determines if another file name is a descendent of this file name.
+     * @param descendent the FileName to check.
+     * @param nameScope the NameScope of the FileName.
+     * @return true if the other FileName is a descendent of this file name.
+     */
+    boolean isDescendent(FileName descendent, NameScope nameScope);
+
+    /**
+     * Returns the requested or current type of this name. <br />
+     * <p>
+     * The "requested" type is the one determined during resolving the name. <br/>
+     * In this case the name is a {@link FileType#FOLDER} if it ends with an "/" else
+     * it will be a {@link FileType#FILE}<br/>
+     * </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}
+     */
+    FileType getType();
+
+    /**
+     * returns a "friendly path", this is a path without a password.<br />
+     * This path can not be used to resolve the path again
+     * @return the friendly URI as a String.
+     */
+    String getFriendlyURI();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFolderException.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFolderException.java
new file mode 100644
index 0000000..ae79073
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFolderException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * delivers a file-not-folder exception which happens when trying to issue {@link FileObject#getChildren()} on a file.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class FileNotFolderException extends FileSystemException
+{
+    public FileNotFolderException(final Object info0)
+    {
+        super("vfs.provider/list-children-not-folder.error", info0);
+    }
+
+    public FileNotFolderException(Object info0, Throwable throwable)
+    {
+        super("vfs.provider/list-children-not-folder.error", info0, throwable);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFoundException.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFoundException.java
new file mode 100644
index 0000000..0d29c72
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileNotFoundException.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * delivers a file-not-found exception.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class FileNotFoundException extends FileSystemException
+{
+    public FileNotFoundException(final Object info0)
+    {
+        super("vfs.provider/read-not-file.error", info0);
+    }
+
+    public FileNotFoundException(Object info0, Throwable throwable)
+    {
+        super("vfs.provider/read-not-file.error", info0, throwable);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileObject.java
new file mode 100644
index 0000000..a57b602
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileObject.java
@@ -0,0 +1,343 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.net.URL;
+import java.util.List;
+
+import org.apache.commons.vfs.operations.FileOperations;
+
+/**
+ * Represents a file, and is used to access the content and
+ * structure of the file.
+ * <p/>
+ * <p>Files are arranged in a hierarchy.  Each hierachy forms a
+ * <i>file system</i>.  A file system represents things like a local OS
+ * file system, a windows share, an HTTP server, or the contents of a Zip file.
+ * <p/>
+ * <p>There are two types of files: <i>Folders</i>, which contain other files,
+ * and <i>normal files</i>, which contain data, or <i>content</i>.  A folder may
+ * not have any content, and a normal file cannot contain other files.
+ * <p/>
+ * <h4>File Naming</h4>
+ * <p/>
+ * <p>TODO - write this.
+ * <p/>
+ * <h4>Reading and Writing a File</h4>
+ * <p/>
+ * <p>Reading and writing a file, and all other operations on the file's
+ * <i>content</i>, is done using the {@link FileContent} object returned
+ * by {@link #getContent}.
+ * <p/>
+ * <h4>Creating and Deleting a File</h4>
+ * <p/>
+ * <p>A file is created using either {@link #createFolder}, {@link #createFile},
+ * or by writing to the file using one of the {@link FileContent} methods.
+ * <p/>
+ * <p>A file is deleted using {@link #delete}.  Recursive deletion can be
+ * done using {@link #delete(FileSelector)}.
+ * <p/>
+ * <h4>Finding Files</h4>
+ * <p/>
+ * <p>Other files in the <i>same</i> file system as this file can be found
+ * using:
+ * <ul>
+ * <li>{@link #resolveFile} to find another file relative to this file.
+ * <li>{@link #getChildren} and {@link #getChild} to find the children of this file.
+ * <li>{@link #getParent} to find the folder containing this file.
+ * <li>{@link #getFileSystem} to find another file in the same file system.
+ * </ul>
+ * <p/>
+ * <p>To find files in another file system, use a {@link FileSystemManager}.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @see FileSystemManager
+ * @see FileContent
+ * @see FileName
+ */
+public interface FileObject
+{
+    /**
+     * Returns the name of this file.
+     * @return the FileName.
+     */
+    FileName getName();
+
+    /**
+     * Returns a URL representing this file.
+     * @return the URL for the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    URL getURL() throws FileSystemException;
+
+    /**
+     * Determines if this file exists.
+     *
+     * @return <code>true</code> if this file exists, <code>false</code> if not.
+     * @throws FileSystemException On error determining if this file exists.
+     */
+    boolean exists() throws FileSystemException;
+
+    /**
+     * Determines if this file is hidden.
+     *
+     * @return <code>true</code> if this file is hidden, <code>false</code> if not.
+     * @throws FileSystemException On error determining if this file exists.
+     */
+    boolean isHidden() throws FileSystemException;
+
+    /**
+     * Determines if this file can be read.
+     *
+     * @return <code>true</code> if this file is readable, <code>false</code> if not.
+     * @throws FileSystemException On error determining if this file exists.
+     */
+    boolean isReadable() throws FileSystemException;
+
+    /**
+     * Determines if this file can be written to.
+     *
+     * @return <code>true</code> if this file is writeable, <code>false</code> if not.
+     * @throws FileSystemException On error determining if this file exists.
+     */
+    boolean isWriteable() throws FileSystemException;
+
+    /**
+     * Returns this file's type.
+     *
+     * @return One of the {@link FileType} constants.  Never returns null.
+     * @throws FileSystemException On error determining the file's type.
+     */
+    FileType getType() throws FileSystemException;
+
+    /**
+     * Returns the folder that contains this file.
+     *
+     * @return The folder that contains this file.  Returns null if this file is
+     *         the root of a file system.
+     * @throws FileSystemException On error finding the file's parent.
+     */
+    FileObject getParent() throws FileSystemException;
+
+    /**
+     * Returns the file system that contains this file.
+     *
+     * @return The file system.
+     */
+    FileSystem getFileSystem();
+
+    /**
+     * Lists the children of this file.
+     *
+     * @return An array containing the children of this file.  The array is
+     *         unordered.  If the file does not have any children, a zero-length
+     *         array is returned.  This method never returns null.
+     * @throws FileSystemException If this file does not exist, or is not a folder, or on error
+     *                             listing this file's children.
+     */
+    FileObject[] getChildren() throws FileSystemException;
+
+    /**
+     * Returns a child of this file.  Note that this method returns <code>null</code>
+     * when the child does not exist.  This differs from
+     * {@link #resolveFile( String, NameScope)} which never returns null.
+     *
+     * @param name The name of the child.
+     * @return The child, or null if there is no such child.
+     * @throws FileSystemException If this file does not exist, or is not a folder, or on error
+     *                             determining this file's children.
+     */
+    FileObject getChild(String name) throws FileSystemException;
+
+    /**
+     * Finds a file, relative to this file.  Refer to {@link NameScope}
+     * for a description of how names are resolved in the different scopes.
+     *
+     * @param name The name to resolve.
+     * @param scope the NameScope for the file.
+     * @return The file.
+     * @throws FileSystemException On error parsing the path, or on error finding the file.
+     */
+    FileObject resolveFile(String name, NameScope scope)
+        throws FileSystemException;
+
+    /**
+     * Finds a file, relative to this file.  Equivalent to calling
+     * <code>resolveFile( path, NameScope.FILE_SYSTEM )</code>.
+     *
+     * @param path The path of the file to locate.  Can either be a relative
+     *             path or an absolute path.
+     * @return The file.
+     * @throws FileSystemException On error parsing the path, or on error finding the file.
+     */
+    FileObject resolveFile(String path) throws FileSystemException;
+
+    /**
+     * Finds the set of matching descendents of this file, in depthwise order.
+     *
+     * @param selector The selector to use to select matching files.
+     * @return The matching files.  The files are returned in depthwise order
+     *         (that is, a child appears in the list before its parent).
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject[] findFiles(FileSelector selector) throws FileSystemException;
+
+    /**
+         * Finds the set of matching descendents of this file.
+         *
+         * @param selector  the selector used to determine if the file should be selected
+         * @param depthwise controls the ordering in the list. e.g. deepest first
+         * @param selected  container for selected files. list needs not to be empty.
+         * @throws FileSystemException if an error occurs.
+         */
+    void findFiles(FileSelector selector, boolean depthwise, List selected) throws FileSystemException;
+
+    /**
+     * Deletes this file.  Does nothing if this file does not exist of if it is a
+     * folder that has children.  Does not delete any descendents of this file,
+     * use {@link #delete(FileSelector)} for that.
+     *
+     * @return true if this object has been deleted
+     * @throws FileSystemException If this file is a non-empty folder, or if this file is read-only,
+     *                             or on error deleteing this file.
+     */
+    boolean delete() throws FileSystemException;
+
+    /**
+     * Deletes all descendents of this file that match a selector.  Does
+     * nothing if this file does not exist.
+     * <p/>
+     * <p>This method is not transactional.  If it fails and throws an
+     * exception, this file will potentially only be partially deleted.
+     *
+     * @param selector The selector to use to select which files to delete.
+     * @return the number of deleted objects
+     * @throws FileSystemException If this file or one of its descendents is read-only, or on error
+     *                             deleting this file or one of its descendents.
+     */
+    int delete(FileSelector selector) throws FileSystemException;
+
+    /**
+     * Creates this folder, if it does not exist.  Also creates any ancestor
+     * folders which do not exist.  This method does nothing if the folder
+     * already exists.
+     *
+     * @throws FileSystemException If the folder already exists with the wrong type, or the parent
+     *                             folder is read-only, or on error creating this folder or one of
+     *                             its ancestors.
+     */
+    void createFolder() throws FileSystemException;
+
+    /**
+     * Creates this file, if it does not exist.  Also creates any ancestor
+     * folders which do not exist.  This method does nothing if the file
+     * already exists and is a file.
+     *
+     * @throws FileSystemException If the file already exists with the wrong type, or the parent
+     *                             folder is read-only, or on error creating this file or one of
+     *                             its ancestors.
+     */
+    void createFile() throws FileSystemException;
+
+    /**
+     * Copies another file, and all its descendents, to this file.
+     * <p/>
+     * If this file does not exist, it is created.  Its parent folder is also
+     * created, if necessary.  If this file does exist, it is deleted first.
+     * <p/>
+     * <p>This method is not transactional.  If it fails and throws an
+     * exception, this file will potentially only be partially copied.
+     *
+     * @param srcFile  The source file to copy.
+     * @param selector The selector to use to select which files to copy.
+     * @throws FileSystemException If this file is read-only, or if the source file does not exist,
+     *                             or on error copying the file.
+     */
+    void copyFrom(FileObject srcFile, FileSelector selector)
+        throws FileSystemException;
+
+    /**
+     * Move this file.
+     * <p>If the destFile exists, it is deleted first</p>
+     *
+     * @param destFile the New filename.
+     * @throws FileSystemException If this file is read-only, or if the source file does not exist,
+     *                             or on error copying the file.
+     */
+    void moveTo(FileObject destFile)
+        throws FileSystemException;
+
+    /**
+     * Queries the file if it is possible to rename it to newfile.
+     *
+     * @param newfile the new file(-name)
+     * @return true it this is the case
+     */
+    boolean canRenameTo(FileObject newfile);
+
+    /**
+     * Returns this file's content.  The {@link FileContent} returned by this
+     * method can be used to read and write the content of the file.
+     * <p/>
+     * <p>This method can be called if the file does not exist, and
+     * the returned {@link FileContent} can be used to create the file
+     * by writing its content.
+     *
+     * @return This file's content.
+     * @throws FileSystemException On error getting this file's content.
+     */
+    FileContent getContent() throws FileSystemException;
+
+    /**
+     * Closes this file, and its content.  This method is a hint to the
+     * implementation that it can release any resources associated with
+     * the file.
+     * <p/>
+     * <p>The file object can continue to be used after this method is called.
+     *
+     * @throws FileSystemException On error closing the file.
+     * @see FileContent#close
+     */
+    void close() throws FileSystemException;
+
+    /**
+     * This will prepare the fileObject to get resynchronized with the underlaying filesystem if required.
+     * @throws FileSystemException if an error occurs.
+     */
+    void refresh() throws FileSystemException;
+
+    /**
+     * check if the fileObject is attaced.
+     * @return true if the FileObject is attached.
+     */
+    boolean isAttached();
+
+    /**
+     * check if someone reads/write to this file.
+     * @return true if the file content is open.
+     */
+    boolean isContentOpen();
+
+
+    // --- OPERATIONS --
+    /**
+     * @return FileOperations interface that provides access to the operations API.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileOperations getFileOperations() throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelectInfo.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelectInfo.java
new file mode 100644
index 0000000..8c6e707
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelectInfo.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Information about a file, that is used to select files during the
+ * traversal of a hierarchy.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Rename this interface, as it is used by both FileSelector and FileVisitor.
+ */
+public interface FileSelectInfo
+{
+    /**
+     * Returns the base folder of the traversal.
+     * @return FileObject representing the base folder.
+     */
+    FileObject getBaseFolder();
+
+    /**
+     * Returns the file (or folder) to be considered.
+     * @return The FileObject.
+     */
+    FileObject getFile();
+
+    /**
+     * Returns the depth of the file relative to the base folder.
+     * @return The depth of the file relative to the base folder.
+     */
+    int getDepth();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelector.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelector.java
new file mode 100644
index 0000000..417027d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSelector.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * This interface is used to select files when traversing a file hierarchy.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @see Selectors
+ */
+public interface FileSelector
+{
+    /**
+     * Determines if a file or folder should be selected.  This method is
+     * called in depthwise order (that is, it is called for the children
+     * of a folder before it is called for the folder itself).
+     *
+     * @param fileInfo the file or folder to select.
+     * @return true if the file should be selected.
+     * @throws Exception if an error occurs.
+     */
+    boolean includeFile(FileSelectInfo fileInfo)
+        throws Exception;
+
+    /**
+     * Determines whether a folder should be traversed.  If this method returns
+     * true, {@link #includeFile} is called for each of the children of
+     * the folder, and each of the child folders is recursively traversed.
+     * <p/>
+     * <p>This method is called on a folder before {@link #includeFile}
+     * is called.
+     *
+     * @param fileInfo the file or folder to select.
+     * @return true if the folder should be traversed.
+     * @throws Exception if an error occurs.
+     */
+    boolean traverseDescendents(FileSelectInfo fileInfo)
+        throws Exception;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystem.java
new file mode 100644
index 0000000..2198b8c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystem.java
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.io.File;
+
+/**
+ * A file system, made up of a hierarchy of files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+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.
+     *
+     * @param capability The capability to check for.
+     * @return true if this filesystem has the requested capability.
+     *         Note that not all files in the file system may have the
+     *         capability.
+     * @todo Move this to another interface, so that set of capabilities can be queried.
+     */
+    boolean hasCapability(Capability capability);
+
+    /**
+     * 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 getParentLayer() throws FileSystemException;
+
+    /**
+     * Gets the value of an attribute of the file system.
+     * <p/>
+     * <p>TODO - change to <code>Map getAttributes()</code> instead?
+     * <p/>
+     * <p>TODO - define the standard attribute names, and define which attrs
+     * are guaranteed to be present.
+     *
+     * @param attrName The name of the attribute.
+     * @return The value of the attribute.
+     * @throws org.apache.commons.vfs.FileSystemException
+     *          If the file does not exist, or is being written, or if the
+     *          attribute is unknown.
+     * @see org.apache.commons.vfs.FileContent#getAttribute
+     */
+    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.
+     *
+     * @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
+     */
+    void setAttribute(String attrName, Object value)
+        throws FileSystemException;
+
+    /**
+     * Finds a file in this file system.
+     *
+     * @param name The name of the file.
+     * @return The file.  Never returns null.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject resolveFile(FileName name) throws FileSystemException;
+
+    /**
+     * Finds a file in this file system.
+     *
+     * @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.
+     */
+    FileObject resolveFile(String name) throws FileSystemException;
+
+    /**
+     * Adds a listener on a file in this file system.
+     *
+     * @param file     The file to attach the listener to.
+     * @param listener The listener to add.
+     */
+    void addListener(FileObject file, FileListener listener);
+
+    /**
+     * 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);
+
+    /**
+     * 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 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).
+     */
+    void addJunction(String junctionPoint, FileObject targetFile)
+        throws FileSystemException;
+
+    /**
+     * Removes a junction from this file system.
+     *
+     * @param junctionPoint The junction to remove.
+     * @throws FileSystemException On error removing the junction.
+     */
+    void removeJunction(String junctionPoint) throws FileSystemException;
+
+    /**
+     * Creates a temporary local copy of a file and its descendents.  If
+     * this file is already a local file, a copy is not made.
+     * <p/>
+     * <p>Note that the local copy may include additonal files, that were
+     * not selected by the given selector.
+     *
+     * @param file     The file to replicate.
+     * @param selector The selector to use to select the files to replicate.
+     * @return The local copy of this file.
+     * @throws FileSystemException If this file does not exist, or on error replicating the file.
+     * @todo Add options to indicate whether the caller is happy to deal with
+     * extra files being present locally (eg if the file has been
+     * replicated previously), or whether the caller expects only
+     * the selected files to be present.
+     */
+    File replicateFile(FileObject file, FileSelector selector)
+        throws FileSystemException;
+
+    /**
+     * Returns the FileSystemOptions used to instantiate this filesystem.
+     * @return The FileSystemOptions.
+     */
+    FileSystemOptions getFileSystemOptions();
+
+    /**
+     * Returns a reference to the FileSytemManager.
+     * @return The FileSystemManager.
+     */
+    FileSystemManager getFileSystemManager();
+
+    /**
+     * Returns the accuracy of the last modification time.
+     *
+     * @return ms 0 perfectly accurate, >0 might be off by this value e.g. sftp 1000ms.
+     */
+    double getLastModTimeAccuracy();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemConfigBuilder.java
new file mode 100644
index 0000000..443dd85
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemConfigBuilder.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Abstract class which has the right to fill FileSystemOptions.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class FileSystemConfigBuilder
+{
+    /** Default prefix to use when resolving system properties */
+    private static final String PREFIX = "vfs.";
+
+    /** The root uri of the file system */
+    private static final String ROOTURI = "rootURI";
+
+    /** The prefix to use when resolving system properties */
+    private final String prefix;
+
+    protected FileSystemConfigBuilder()
+    {
+        this.prefix = PREFIX;
+    }
+    protected FileSystemConfigBuilder(String component)
+    {
+        this.prefix = PREFIX + component;
+    }
+
+    /**
+     * The root URI of the file system.
+     * @param opts The FileSystem options
+     * @param rootURI The creator name to be associated with the file.
+     */
+    public void setRootURI(FileSystemOptions opts, String rootURI)
+    {
+        setParam(opts, ROOTURI, rootURI);
+    }
+
+    /**
+     * Return the root URI of the file system.
+     * @param opts The FileSystem options
+     * @return The root URI.
+     */
+    public String getRootURI(FileSystemOptions opts)
+    {
+        return getString(opts, ROOTURI);
+    }
+
+
+    protected void setParam(FileSystemOptions opts, String name, Object value)
+    {
+        opts.setOption(getConfigClass(), name, value);
+    }
+
+    protected Object getParam(FileSystemOptions opts, String name)
+    {
+        if (opts == null)
+        {
+            return null;
+        }
+
+        return opts.getOption(getConfigClass(), name);
+    }
+
+    protected boolean hasParam(FileSystemOptions opts, String name)
+    {
+        return opts != null && opts.hasOption(getConfigClass(), name);
+    }
+
+    protected boolean hasObject(FileSystemOptions opts, String name)
+    {
+        return hasParam(opts, name) || System.getProperties().containsKey(PREFIX + name);
+    }
+
+    protected Boolean getBoolean(FileSystemOptions opts, String name)
+    {
+        return getBoolean(opts, name, null);
+    }
+
+    protected boolean getBoolean(FileSystemOptions opts, String name, boolean defaultValue)
+    {
+        return getBoolean(opts, name, new Boolean(defaultValue)).booleanValue();
+    }
+
+    protected Boolean getBoolean(FileSystemOptions opts, String name, Boolean defaultValue)
+    {
+        Boolean value = (Boolean) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(PREFIX + name);
+            if (str == null)
+            {
+                return defaultValue;
+            }
+            value = Boolean.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Byte getByte(FileSystemOptions opts, String name)
+    {
+        return getByte(opts, name, null);
+    }
+
+    protected byte getByte(FileSystemOptions opts, String name, byte defaultValue)
+    {
+        return getByte(opts, name, new Byte(defaultValue)).byteValue();
+    }
+
+    protected Byte getByte(FileSystemOptions opts, String name, Byte defaultValue)
+    {
+        Byte value = (Byte) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null)
+            {
+                return defaultValue;
+            }
+            value = Byte.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Character getCharacter(FileSystemOptions opts, String name)
+    {
+        return getCharacter(opts, name, null);
+    }
+
+    protected char getCharacter(FileSystemOptions opts, String name, char defaultValue)
+    {
+        return getCharacter(opts, name, new Character(defaultValue)).charValue();
+    }
+
+    protected Character getCharacter(FileSystemOptions opts, String name, Character defaultValue)
+    {
+        Character value = (Character) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null || str.length() <= 0)
+            {
+                return defaultValue;
+            }
+            value = new Character(str.charAt(0));
+        }
+        return value;
+    }
+
+    protected Double getDouble(FileSystemOptions opts, String name)
+    {
+        return getDouble(opts, name, null);
+    }
+
+    protected double getDouble(FileSystemOptions opts, String name, double defaultValue)
+    {
+        return getDouble(opts, name, new Double(defaultValue)).doubleValue();
+    }
+
+    protected Double getDouble(FileSystemOptions opts, String name, Double defaultValue)
+    {
+        Double value = (Double) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null || str.length() <= 0)
+            {
+                return defaultValue;
+            }
+            value = Double.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Float getFloat(FileSystemOptions opts, String name)
+    {
+        return getFloat(opts, name, null);
+    }
+
+    protected float getFloat(FileSystemOptions opts, String name, float defaultValue)
+    {
+        return getFloat(opts, name, new Float(defaultValue)).floatValue();
+    }
+
+    protected Float getFloat(FileSystemOptions opts, String name, Float defaultValue)
+    {
+        Float value = (Float) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null || str.length() <= 0)
+            {
+                return defaultValue;
+            }
+            value = Float.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Integer getInteger(FileSystemOptions opts, String name)
+    {
+        return getInteger(opts, name, null);
+    }
+
+    protected int getInteger(FileSystemOptions opts, String name, int defaultValue)
+    {
+        return getInteger(opts, name, new Integer(defaultValue)).intValue();
+    }
+
+    protected Integer getInteger(FileSystemOptions opts, String name, Integer defaultValue)
+    {
+        Integer value = (Integer) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null)
+            {
+                return defaultValue;
+            }
+            value = Integer.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Long getLong(FileSystemOptions opts, String name)
+    {
+        return getLong(opts, name, null);
+    }
+
+    protected long getLong(FileSystemOptions opts, String name, long defaultValue)
+    {
+        return getLong(opts, name, new Long(defaultValue)).longValue();
+    }
+
+    protected Long getLong(FileSystemOptions opts, String name, Long defaultValue)
+    {
+        Long value = (Long) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null)
+            {
+                return defaultValue;
+            }
+            value = Long.valueOf(str);
+        }
+        return value;
+    }
+
+    protected Short getShort(FileSystemOptions opts, String name)
+    {
+        return getShort(opts, name, null);
+    }
+
+    protected short getShort(FileSystemOptions opts, String name, short defaultValue)
+    {
+        return getShort(opts, name, new Short(defaultValue)).shortValue();
+    }
+
+    protected Short getShort(FileSystemOptions opts, String name, Short defaultValue)
+    {
+        Short value = (Short) getParam(opts, name);
+        if (value == null)
+        {
+            String str = System.getProperty(this.prefix + name);
+            if (str == null)
+            {
+                return defaultValue;
+            }
+            value = Short.valueOf(str);
+        }
+        return value;
+    }
+
+    protected String getString(FileSystemOptions opts, String name)
+    {
+        return getString(opts, name, null);
+    }
+
+    protected String getString(FileSystemOptions opts, String name, String defaultValue)
+    {
+        String value = (String) getParam(opts, name);
+        if (value == null)
+        {
+            value = System.getProperty(this.prefix + name);
+            if (value == null)
+            {
+                return defaultValue;
+            }
+        }
+        return value;
+    }
+
+    protected abstract Class getConfigClass();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemException.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemException.java
new file mode 100644
index 0000000..17fc676
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemException.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import org.apache.commons.vfs.util.Messages;
+
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Thrown for file system errors.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileSystemException
+    extends IOException
+{
+    /** URL pattern */
+    private static final Pattern URL_PATTERN = Pattern.compile("[a-z]+://.*");
+
+    /** Password pattern */
+    private static final Pattern PASSWORD_PATTERN = Pattern.compile(":(?:[^/]+)@");
+
+    /**
+     * The Throwable that caused this exception to be thrown.
+     */
+    private final Throwable throwable;
+
+    /**
+     * The message code.
+     */
+    private final String code;
+
+    /**
+     * array of complementary info (context).
+     */
+    private final String[] info;
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code the error code of the message.
+     */
+    public FileSystemException(final String code)
+    {
+        this(code, null, null);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code  the error code of the message.
+     * @param info0 one context information.
+     */
+    public FileSystemException(final String code, final Object info0)
+    {
+        this(code, new Object[]{info0}, null);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code      the error code of the message.
+     * @param info0     one context information.
+     * @param throwable the cause.
+     */
+    public FileSystemException(final String code,
+                               final Object info0,
+                               final Throwable throwable)
+    {
+        this(code, new Object[]{info0}, throwable);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code the error code of the message.
+     * @param info array of complementary info (context).
+     */
+    public FileSystemException(final String code, final Object[] info)
+    {
+        this(code, info, null);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code the error code of the message.
+     * @param throwable the original cause
+     */
+    public FileSystemException(final String code, final Throwable throwable)
+    {
+        this(code, null, throwable);
+    }
+
+    /**
+     * Constructs exception with the specified detail message.
+     *
+     * @param code      the error code of the message.
+     * @param info      array of complementary info (context).
+     * @param throwable the cause.
+     */
+    public FileSystemException(final String code,
+                               final Object[] info,
+                               final Throwable throwable)
+    {
+        super(code);
+
+        if (info == null)
+        {
+            this.info = new String[0];
+        }
+        else
+        {
+            this.info = new String[info.length];
+            for (int i = 0; i < info.length; i++)
+            {
+                String value = String.valueOf(info[i]);
+                // mask passwords (VFS-169)
+                final Matcher urlMatcher = URL_PATTERN.matcher(value);
+                if (urlMatcher.find())
+                {
+                    final Matcher pwdMatcher = PASSWORD_PATTERN.matcher(value);
+                    value = pwdMatcher.replaceFirst(":***@");
+                }
+                this.info[i] = value;
+            }
+        }
+        this.code = code;
+        this.throwable = throwable;
+    }
+
+    /**
+     * Constructs wrapper exception.
+     *
+     * @param throwable the root cause to wrap.
+     */
+    public FileSystemException(final Throwable throwable)
+    {
+        this(throwable.getMessage(), null, throwable);
+    }
+
+    /**
+     * retrieve message from bundle.
+     * @return The exception message.
+     */
+    public String getMessage()
+    {
+        return Messages.getString(super.getMessage(), getInfo());
+    }
+
+    /**
+     * Retrieve root cause of the exception.
+     *
+     * @return the root cause
+     */
+    public final Throwable getCause()
+    {
+        return throwable;
+    }
+
+    /**
+     * Retrieve error code of the exception.
+     * Could be used as key for internationalization.
+     *
+     * @return the code.
+     */
+    public String getCode()
+    {
+        return code;
+    }
+
+    /**
+     * Retrieve array of complementary info (context).
+     * Could be used as parameter for internationalization.
+     *
+     * @return the context info.
+     */
+    public String[] getInfo()
+    {
+        return info;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemManager.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemManager.java
new file mode 100644
index 0000000..8fb08c8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemManager.java
@@ -0,0 +1,342 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import org.apache.commons.logging.Log;
+
+import java.io.File;
+import java.net.URLStreamHandlerFactory;
+import java.util.Collection;
+import java.lang.reflect.Constructor;
+
+import org.apache.commons.vfs.operations.FileOperationProvider;
+
+/**
+ * A FileSystemManager manages a set of file systems.  This interface is
+ * used to locate a {@link FileObject} by name from one of those file systems.
+ * <p/>
+ * <p>To locate a {@link FileObject}, use one of the <code>resolveFile()</code>
+ * methods.</p>
+ * <p/>
+ * <h4><a name="naming">File Naming</a></h4>
+ * <p/>
+ * <p>A file system manager can recognise several types of file names:
+ * <p/>
+ * <ul>
+ * <p/>
+ * <li><p>Absolute URI.  These must start with a scheme, such as
+ * <code>file:</code> or <code>ftp:</code>, followed by a scheme dependent
+ * file name.  Some examples:</p>
+ * <pre>
+ * file:/c:/somefile
+ * ftp://somewhere.org/somefile
+ * </pre>
+ * <p/>
+ * <li><p>Absolute local file name.  For example,
+ * <code>/home/someuser/a-file</code> or <code>c:\dir\somefile.html</code>.
+ * Elements in the name can be separated using any of the following
+ * characters: <code>/</code>, <code>\</code>, or the native file separator
+ * character. For example, the following file names are the same:</p>
+ * <pre>
+ * c:\somedir\somefile.xml
+ * c:/somedir/somefile.xml
+ * </pre>
+ * <p/>
+ * <li><p>Relative path.  For example: <code>../somefile</code> or
+ * <code>somedir/file.txt</code>.   The file system manager resolves relative
+ * paths against its <i>base file</i>.  Elements in the relative path can be
+ * separated using <code>/</code>, <code>\</code>, or file system specific
+ * separator characters.  Relative paths may also contain <code>..</code> and
+ * <code>.</code> elements.  See {@link FileObject#resolveFile} for more
+ * details.</p>
+ * <p/>
+ * </ul>
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileSystemManager
+{
+    /**
+     * Returns the base file used to resolve relative paths.
+     * @return The base FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject getBaseFile() throws FileSystemException;
+
+    /**
+     * Locates a file by name.  Equivalent to calling
+     * <code>resolveFile(uri, getBaseName())</code>.
+     *
+     * @param name The name of the file.
+     * @return The file.  Never returns null.
+     * @throws FileSystemException On error parsing the file name.
+     */
+    FileObject resolveFile(String name) throws FileSystemException;
+
+    /**
+     * Locates a file by name.  Equivalent to calling
+     * <code>resolveFile(uri, getBaseName())</code>.
+     *
+     * @param name              The name of the file.
+     * @param fileSystemOptions The FileSystemOptions used for FileSystem creation
+     * @return The file.  Never returns null.
+     * @throws FileSystemException On error parsing the file name.
+     */
+    FileObject resolveFile(String name, FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    /**                               §
+     * Locates a file by name.  The name is resolved as described
+     * <a href="#naming">above</a>.  That is, the name can be either
+     * an absolute URI, an absolute file name, or a relative path to
+     * be resolved against <code>baseFile</code>.
+     * <p/>
+     * <p>Note that the file does not have to exist when this method is called.
+     *
+     * @param name     The name of the file.
+     * @param baseFile The base file to use to resolve relative paths.
+     *                 May be null.
+     * @return The file.  Never returns null.
+     * @throws FileSystemException On error parsing the file name.
+     */
+    FileObject resolveFile(FileObject baseFile, String name) throws FileSystemException;
+
+    /**
+     * Locates a file by name.  See {@link #resolveFile(FileObject, String)}
+     * for details.
+     *
+     * @param baseFile The base file to use to resolve relative paths.
+     *                 May be null.
+     * @param name     The name of the file.
+     * @return The file.  Never returns null.
+     * @throws FileSystemException On error parsing the file name.
+     */
+    FileObject resolveFile(File baseFile, String name) throws FileSystemException;
+
+    /**
+     * Resolves a name, relative to this file name.  Equivalent to calling
+     * <code>resolveName( path, NameScope.FILE_SYSTEM )</code>.
+     *
+     * @param root the base filename
+     * @param name The name to resolve.
+     * @return A {@link FileName} object representing the resolved file name.
+     * @throws FileSystemException If the name is invalid.
+     */
+    FileName resolveName(final FileName root, final String name) throws FileSystemException;
+
+    /**
+     * Resolves a name, relative to the "root" file name.  Refer to {@link NameScope}
+     * for a description of how names are resolved.
+     *
+     * @param root the base filename
+     * @param name  The name to resolve.
+     * @param scope The {@link NameScope} to use when resolving the name.
+     * @return A {@link FileName} object representing the resolved file name.
+     * @throws FileSystemException If the name is invalid.
+     */
+    FileName resolveName(final FileName root, String name, NameScope scope)
+        throws FileSystemException;
+
+    /**
+     * Converts a local file into a {@link FileObject}.
+     *
+     * @param file The file to convert.
+     * @return The {@link FileObject} that represents the local file.  Never
+     *         returns null.
+     * @throws FileSystemException On error converting the file.
+     */
+    FileObject toFileObject(File file) throws FileSystemException;
+
+    /**
+     * Creates a layered file system.  A layered file system is a file system
+     * that is created from the contents of a file, such as a zip or tar file.
+     *
+     * @param provider The name of the file system provider to use.  This name
+     *                 is the same as the scheme used in URI to identify the provider.
+     * @param file     The file to use to create the file system.
+     * @return The root file of the new file system.
+     * @throws FileSystemException On error creating the file system.
+     */
+    FileObject createFileSystem(String provider, FileObject file)
+        throws FileSystemException;
+
+    /**
+     * Closes the given filesystem.<br />
+     * If you use VFS as singleton it is VERY dangerous to call this method.
+     * @param filesystem The FileSystem to close.
+     */
+    void closeFileSystem(FileSystem filesystem);
+
+    /**
+     * Creates a layered file system.  A layered file system is a file system
+     * that is created from the contents of a file, such as a zip or tar file.
+     *
+     * @param file The file to use to create the file system.
+     * @return The root file of the new file system.
+     * @throws FileSystemException On error creating the file system.
+     */
+    FileObject createFileSystem(FileObject file) throws FileSystemException;
+
+    /**
+     * Creates an empty virtual file system.  Can be populated by adding
+     * junctions to it.
+     *
+     * @param rootUri The root URI to use for the new file system.  Can be null.
+     * @return The root file of the new file system.
+     * @throws FileSystemException if an error occurs creating the VirtualFileSystem.
+     */
+    FileObject createVirtualFileSystem(String rootUri) throws FileSystemException;
+
+    /**
+     * Creates a virtual file system.  The file system will contain a junction
+     * at the fs root to the supplied root file.
+     *
+     * @param rootFile The root file to backs the file system.
+     * @return The root of the new file system.
+     * @throws FileSystemException if an error occurs creating the VirtualFileSystem.
+     */
+    FileObject createVirtualFileSystem(FileObject rootFile) throws FileSystemException;
+
+    /**
+     * Returns a streamhandler factory to enable URL lookup using this
+     * FileSystemManager.
+     * @return the URLStreamHandlerFactory.
+     */
+    URLStreamHandlerFactory getURLStreamHandlerFactory();
+
+    /**
+     * Determines if a layered file system can be created for a given file.
+     *
+     * @param file The file to check for.
+     * @return true if the FileSystem can be created.
+     * @throws FileSystemException if an error occurs.
+     */
+    boolean canCreateFileSystem(FileObject file) throws FileSystemException;
+
+    /**
+     * Get the cache used to cache fileobjects.
+     * @return The FilesCache.
+     */
+    FilesCache getFilesCache();
+
+    /**
+     * Get the cache strategy used.
+     * @return the CacheStrategy.
+     */
+    CacheStrategy getCacheStrategy();
+
+    /**
+     * Get the file object decorator used.
+     * @return the file object decorator Class.
+     */
+    Class getFileObjectDecorator();
+
+    /**
+     * The constructor associated to the fileObjectDecorator.
+     * We cache it here for performance reasons.
+     * @return the Constructor associated with the FileObjectDecorator.
+     */
+    Constructor getFileObjectDecoratorConst();
+
+    /**
+     * The class to use to determine the content-type (mime-type).
+     * @return the FileContentInfoFactory.
+     */
+    FileContentInfoFactory getFileContentInfoFactory();
+
+    /**
+     * Returns true if this manager has a provider for a particular scheme.
+     * @param scheme The scheme for which a provider should be checked.
+     * @return true if a provider for the scheme is available.
+     */
+    boolean hasProvider(final String scheme);
+
+    /**
+     * Get the schemes currently available.
+     * @return An array of available scheme names that are supported.
+     */
+    String[] getSchemes();
+
+    /**
+     * Get the capabilities for a given scheme.
+     *
+     * @param scheme The scheme to use to locate the provider's capabilities.
+     * @return A Collection of the various capabilities.
+     * @throws FileSystemException if the given scheme is not konwn.
+     */
+    Collection getProviderCapabilities(final String scheme) throws FileSystemException;
+
+    /**
+     * Sets the logger to use.
+     * @param log The logger to use.
+     */
+    void setLogger(final Log log);
+
+    /**
+     * Get the configuration builder for the given scheme.
+     *
+     * @param scheme The schem to use to obtain the FileSystemConfigBuidler.
+     * @return A FileSystemConfigBuilder appropriate for the given scheme.
+     * @throws FileSystemException if the given scheme is not konwn.
+     */
+    FileSystemConfigBuilder getFileSystemConfigBuilder(final String scheme) throws FileSystemException;
+
+    /**
+     * Resolve the uri to a filename.
+     *
+     * @param uri The uri to resolve.
+     * @return A FileName that matches the uri.
+     * @throws FileSystemException if this is not possible.
+     */
+    FileName resolveURI(String uri) throws FileSystemException;
+
+    // -- OPERATIONS --
+    /**
+     * Adds the specified FileOperationProvider for the specified scheme.
+     * Several FileOperationProvider's might be registered for the same scheme.
+     * For example, for "file" scheme we can register SvnWsOperationProvider and
+     * CvsOperationProvider.
+     *
+     * @param scheme The scheme assoicated with this provider.
+     * @param operationProvider The FileOperationProvider to add.
+     * @throws FileSystemException if an error occurs.
+     */
+    void addOperationProvider(final String scheme, final FileOperationProvider operationProvider)
+        throws FileSystemException;
+
+    /**
+     * @see FileSystemManager#addOperationProvider(String, org.apache.commons.vfs.operations.FileOperationProvider)
+     *
+     * @param schemes The schemes that will be associated with the provider.
+     * @param operationProvider The FileOperationProvider to add.
+     * @throws FileSystemException if an error occurs.
+     */
+    void addOperationProvider(final String[] schemes, final FileOperationProvider operationProvider)
+        throws FileSystemException;
+
+
+    /**
+     * @param scheme the scheme for wich we want to get the list af registered providers.
+     *
+     * @return the registered FileOperationProviders for the specified scheme.
+     * If there were no providers registered for the scheme, it returns null.
+     *
+     * @throws FileSystemException if an error occurs.
+     */
+    FileOperationProvider[] getOperationProviders(final String scheme) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemOptions.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemOptions.java
new file mode 100644
index 0000000..387473c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileSystemOptions.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Container for FileSystemOptions.<br>
+ * You have to use *FileSystemConfigBuilder.getInstance() to fill this container<br>
+ * * = the filesystem provider short name
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ * @see org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder
+ * @see org.apache.commons.vfs.provider.ftp.FtpFileSystemConfigBuilder
+ */
+public final class FileSystemOptions implements Cloneable
+{
+    /** The options */
+    private Map options = new TreeMap();
+
+    /**
+     * Keys in the options Map.
+     */
+    private static final class FileSystemOptionKey implements Comparable
+    {
+        /** Constant used to create hashcode */
+        private static final int HASH = 29;
+
+        /** The FileSystem class */
+        private final Class fileSystemClass;
+
+        /** The option name */
+        private final String name;
+
+        private FileSystemOptionKey(Class fileSystemClass, String name)
+        {
+            this.fileSystemClass = fileSystemClass;
+            this.name = name;
+        }
+
+        public int compareTo(Object o)
+        {
+            FileSystemOptionKey k = (FileSystemOptionKey) o;
+
+            int ret = fileSystemClass.getName().compareTo(k.fileSystemClass.getName());
+            if (ret != 0)
+            {
+                return ret;
+            }
+
+            return name.compareTo(k.name);
+        }
+
+        public boolean equals(Object o)
+        {
+            if (this == o)
+            {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass())
+            {
+                return false;
+            }
+
+            final FileSystemOptionKey that = (FileSystemOptionKey) o;
+
+            if (!fileSystemClass.equals(that.fileSystemClass))
+            {
+                return false;
+            }
+            if (!name.equals(that.name))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public int hashCode()
+        {
+            int result;
+            result = fileSystemClass.hashCode();
+            result = HASH * result + name.hashCode();
+            return result;
+        }
+    }
+
+    public FileSystemOptions()
+    {
+    }
+
+    void setOption(Class fileSystemClass, String name, Object value)
+    {
+        options.put(new FileSystemOptionKey(fileSystemClass, name), value);
+    }
+
+    Object getOption(Class fileSystemClass, String name)
+    {
+        FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
+        return options.get(key);
+    }
+
+    boolean hasOption(Class fileSystemClass, String name)
+    {
+        FileSystemOptionKey key = new FileSystemOptionKey(fileSystemClass, name);
+        return options.containsKey(key);
+    }
+
+    public int compareTo(FileSystemOptions other)
+    {
+        if (this == other)
+        {
+            // the same instance
+            return 0;
+        }
+
+        int propsSz = options == null ? 0 : options.size();
+        int propsFkSz = other.options == null ? 0 : other.options.size();
+        if (propsSz < propsFkSz)
+        {
+            return -1;
+        }
+        if (propsSz > propsFkSz)
+        {
+            return 1;
+        }
+        if (propsSz == 0)
+        {
+            // props empty
+            return 0;
+        }
+
+        int hash = options.hashCode();
+        int hashFk = other.options.hashCode();
+        if (hash < hashFk)
+        {
+            return -1;
+        }
+        if (hash > hashFk)
+        {
+            return 1;
+        }
+
+        // bad props not the same instance, but looks like the same
+        // TODO: compare Entry by Entry
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object clone()
+    {
+        FileSystemOptions clone = new FileSystemOptions();
+        clone.options = new TreeMap(options);
+        return clone;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileType.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileType.java
new file mode 100644
index 0000000..95539b8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileType.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * An enumerated type that represents a file's type.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class FileType
+{
+    /**
+     * A folder.  May contain other files, and have attributes, but does not
+     * have any data content.
+     */
+    public static final FileType FOLDER = new FileType("folder", true, false, true);
+
+    /**
+     * A regular file.  May have data content and attributes, but cannot
+     * contain other files.
+     */
+    public static final FileType FILE = new FileType("file", false, true, true);
+
+    /**
+     * A file or folder.  May have data content and attributes, and can
+     * contain other files.
+     */
+    public static final FileType FILE_OR_FOLDER = new FileType("fileOrFolder", true, true, true);
+
+    /**
+     * A file that does not exist.  May not have data content, attributes,
+     * or contain other files.
+     */
+    public static final FileType IMAGINARY = new FileType("imaginary", false, false, false);
+
+    /** The name of the FileType */
+    private final String name;
+
+    /** true if the FileType can have children */
+    private final boolean hasChildren;
+
+    /** true if the FileType can have content */
+    private final boolean hasContent;
+
+    /** true if the FileType has attributes */
+    private final boolean hasAttrs;
+
+    private FileType(final String name,
+                     final boolean hasChildren,
+                     final boolean hasContent,
+                     final boolean hasAttrs)
+    {
+        this.name = name;
+        this.hasChildren = hasChildren;
+        this.hasContent = hasContent;
+        this.hasAttrs = hasAttrs;
+    }
+
+    /**
+     * Returns the name of this type.
+     * @return The name of this type.
+     */
+    public String toString()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the name of this type.
+     * @return The name of the type.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Returns true if files of this type may contain other files.
+     * @return tru if files can contain other files.
+     */
+    public boolean hasChildren()
+    {
+        return hasChildren;
+    }
+
+    /**
+     * Returns true if files of this type may have data content.
+     * @return true if files can have content.
+     */
+    public boolean hasContent()
+    {
+        return hasContent;
+    }
+
+    /**
+     * Returns true if files of this type may have attributes.
+     * @return true if files can have attributes
+     */
+    public boolean hasAttributes()
+    {
+        return hasAttrs;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeHasNoContentException.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeHasNoContentException.java
new file mode 100644
index 0000000..74cf2f4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeHasNoContentException.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * delivers a file-not-folder exception which happens when trying to issue
+ * {@link org.apache.commons.vfs.FileObject#getChildren()} on a file.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class FileTypeHasNoContentException extends FileSystemException
+{
+    public FileTypeHasNoContentException(final Object info0)
+    {
+        super("vfs.provider/read-not-file.error", info0);
+    }
+
+    public FileTypeHasNoContentException(Object info0, Throwable throwable)
+    {
+        super("vfs.provider/read-not-file.error", info0, throwable);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeSelector.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeSelector.java
new file mode 100644
index 0000000..013c559
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileTypeSelector.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * A {@link FileSelector} that selects files of a particular type.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileTypeSelector
+    implements FileSelector
+{
+    /** The FileType */
+    private final FileType type;
+
+    public FileTypeSelector(final FileType type)
+    {
+        this.type = type;
+    }
+
+    /**
+     * Determines if a file or folder should be selected.
+     * @param fileInfo The file selection information.
+     * @return true if the file or folder should be selected.
+     * @throws FileSystemException if an error occurs
+     */
+    public boolean includeFile(final FileSelectInfo fileInfo)
+        throws FileSystemException
+    {
+        return fileInfo.getFile().getType() == type;
+    }
+
+    /**
+     * Determines whether a folder should be traversed.
+     * @param fileInfo The file selection information.
+     * @return true if the file or folder should be traversed.
+     */
+    public boolean traverseDescendents(final FileSelectInfo fileInfo)
+    {
+        return true;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileUtil.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileUtil.java
new file mode 100644
index 0000000..c0b5f12
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FileUtil.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Utility methods for dealng with FileObjects.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class FileUtil
+{
+
+    /** The buffer size */
+    private static final int BUFFER_SIZE = 1024;
+
+    private FileUtil()
+    {
+    }
+
+    /**
+     * Returns the content of a file, as a byte array.
+     *
+     * @param file The file to get the content of.
+     * @return The content as a byte array.
+     * @throws IOException if the file content cannot be accessed.
+     */
+    public static byte[] getContent(final FileObject file)
+        throws IOException
+    {
+        final FileContent content = file.getContent();
+        final int size = (int) content.getSize();
+        final byte[] buf = new byte[size];
+
+        final InputStream in = content.getInputStream();
+        try
+        {
+            int read = 0;
+            for (int pos = 0; pos < size && read >= 0; pos += read)
+            {
+                read = in.read(buf, pos, size - pos);
+            }
+        }
+        finally
+        {
+            in.close();
+        }
+
+        return buf;
+    }
+
+    /**
+     * Writes the content of a file to an OutputStream.
+     * @param file The FileObject to write.
+     * @param outstr The OutputStream to write to.
+     * @throws IOException if an error occurs writing the file.
+     */
+    public static void writeContent(final FileObject file,
+                                    final OutputStream outstr)
+        throws IOException
+    {
+        final InputStream instr = file.getContent().getInputStream();
+        try
+        {
+            final byte[] buffer = new byte[BUFFER_SIZE];
+            while (true)
+            {
+                final int nread = instr.read(buffer);
+                if (nread < 0)
+                {
+                    break;
+                }
+                outstr.write(buffer, 0, nread);
+            }
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+
+    /**
+     * Copies the content from a source file to a destination file.
+     * @param srcFile The source FileObject.
+     * @param destFile The target FileObject
+     * @throws IOException If an error occurs copying the file.
+     */
+    public static void copyContent(final FileObject srcFile,
+                                   final FileObject destFile)
+        throws IOException
+    {
+        // Create the output stream via getContent(), to pick up the
+        // validation it does
+        final OutputStream outstr = destFile.getContent().getOutputStream();
+        try
+        {
+            writeContent(srcFile, outstr);
+        }
+        finally
+        {
+            outstr.close();
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FilesCache.java
new file mode 100644
index 0000000..6128132
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/FilesCache.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+
+/**
+ * The fileCache interface.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public interface FilesCache
+{
+    /**
+     * add a fileobject to the cache.
+     *
+     * @param file the file
+     */
+    void putFile(final FileObject file);
+
+    /**
+     * retrieve a file from the cache by its name.
+     *
+     * @param filesystem The FileSystem.
+     * @param name the name
+     * @return the fileobject or null if file is not cached
+     */
+    FileObject getFile(final FileSystem filesystem, final FileName name);
+
+    /**
+     * purge the entries corresponding to the filesystem.
+     * @param filesystem The FileSystem.
+     */
+    void clear(final FileSystem filesystem);
+
+    /**
+     * purge the whole cache.
+     */
+    void close();
+
+    /**
+     * removes a file from cache.
+     *
+     * @param filesystem filesystem
+     * @param name       filename
+     */
+    void removeFile(final FileSystem filesystem, final FileName name);
+
+    /**
+     * if the cache uses timestamps it could use this method to handle
+     * updates of them.
+     *
+     * @param file filename
+     */
+    // public void touchFile(final FileObject file);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/NameScope.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/NameScope.java
new file mode 100644
index 0000000..baebc80
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/NameScope.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * An enumerated type for file name scope, used when resolving a name relative
+ * to a file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class NameScope
+{
+    /**
+     * Resolve against the children of the base file.  The name is resolved
+     * as described by {@link #FILE_SYSTEM}.  However, an exception is
+     * thrown if the resolved file is not a direct child of the base file.
+     */
+    public static final NameScope CHILD = new NameScope("child");
+
+    /**
+     * Resolve against the descendents of the base file.  The name is resolved
+     * as described by {@link #FILE_SYSTEM}.  However, an exception is thrown
+     * if the resolved file is not a descendent of the base file.
+     */
+    public static final NameScope DESCENDENT = new NameScope("descendent");
+
+    /**
+     * Resolve against the descendents of the base file.  The name is resolved
+     * as described by {@link #FILE_SYSTEM}.  However, an exception is thrown
+     * if the resolved file is not a descendent of the base file, or the base
+     * files itself.
+     */
+    public static final NameScope DESCENDENT_OR_SELF =
+        new NameScope("descendent_or_self");
+
+    /**
+     * Resolve against files in the same file system as the base file.
+     * <p/>
+     * <p>If the supplied name is an absolute path, then it is resolved
+     * relative to the root of the file system that the base file belongs to.
+     * If a relative name is supplied, then it is resolved relative to the base
+     * file.
+     * <p/>
+     * <p>The path may use any mix of <code>/</code>, <code>\</code>, or file
+     * system specific separators to separate elements in the path.  It may
+     * also contain <code>.</code> and <code>..</code> elements.
+     * <p/>
+     * <p>A path is considered absolute if it starts with a separator character,
+     * and relative if it does not.
+     */
+    public static final NameScope FILE_SYSTEM = new NameScope("filesystem");
+
+    /** The name */
+    private final String name;
+
+    private NameScope(final String name)
+    {
+        this.name = name;
+    }
+
+    /**
+     * Returns the name of the scope.
+     * @return The name of the scope.
+     */
+    public String toString()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the name of the scope.
+     * @return The name of the scope.
+     */
+    public String getName()
+    {
+        return name;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/RandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/RandomAccessContent.java
new file mode 100644
index 0000000..4c716b4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/RandomAccessContent.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Random Access Content.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public interface RandomAccessContent extends DataOutput, DataInput
+{
+    /**
+     * Returns the current offset in this file.
+     *
+     * @return the offset from the beginning of the file, in bytes,
+     *         at which the next read or write occurs.
+     * @throws IOException if an I/O error occurs.
+     */
+    long getFilePointer() throws IOException;
+
+    /**
+     * Sets the file-pointer offset, measured from the beginning of this
+     * file, at which the next read or write occurs.  The offset may be
+     * set beyond the end of the file. Setting the offset beyond the end
+     * of the file does not change the file length.  The file length will
+     * change only by writing after the offset has been set beyond the end
+     * of the file.
+     * <br/>
+     * <b>Notice: If you use {@link #getInputStream()} you have to reget the InputStream after
+     * calling {@link #seek(long)}</b>
+     *
+     * @param pos the offset position, measured in bytes from the
+     *            beginning of the file, at which to set the file
+     *            pointer.
+     * @throws IOException if <code>pos</code> is less than
+     *                     <code>0</code> or if an I/O error occurs.
+     */
+    void seek(long pos) throws IOException;
+
+    /**
+     * Returns the length of this file.
+     *
+     * @return the length of this file, measured in bytes.
+     * @throws IOException if an I/O error occurs.
+     */
+    long length() throws IOException;
+
+    /**
+     * Closes this random access file stream and releases any system
+     * resources associated with the stream. A closed random access
+     * file cannot perform input or output operations and cannot be
+     * reopened.
+     * <p/>
+     * <p> If this file has an associated channel then the channel is closed
+     * as well.
+     *
+     * @throws IOException if an I/O error occurs.
+     */
+    void close() throws IOException;
+
+    /**
+     * Get the input stream.
+     * <br/>
+     * <b>Notice: If you use {@link #seek(long)} you have to reget the InputStream</b>
+     * @return the InputStream.
+     * @throws IOException if an I/O error occurs.
+     */
+    InputStream getInputStream() throws IOException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Resources.properties b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Resources.properties
new file mode 100644
index 0000000..07d11dc
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Resources.properties
@@ -0,0 +1,285 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You under the Apache License, Version 2.0
+#   (the "License"); you may not use this file except in compliance with
+#   the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+# $Id$
+
+# Factory
+vfs/create-manager.error=Could not create a file system manager of class "{0}".
+
+# AbstractFileObject
+vfs.provider/delete-not-supported.error=This file type does not support delete.
+vfs.provider/rename-not-supported.error=This file type does not support rename.
+vfs.provider/write-append-not-supported.error=The file type does not support append mode.
+vfs.provider/random-access-not-supported.error=The file type does not support random access.
+vfs.provider/random-access-read-not-supported.error=The file type does not support read in random access mode.
+vfs.provider/random-access-write-not-supported.error=The file type does not support write in random access mode.
+vfs.provider/create-folder-not-supported.error=This file type does not support folder creation.
+vfs.provider/get-last-modified-not-supported.error=This file type does not support retriving last modified time.
+vfs.provider/set-last-modified-not-supported.error=This file type does not support setting last modified time.
+vfs.provider/set-attribute-not-supported.error=This file type does not support setting attributes.
+vfs.provider/remove-attribute-not-supported.error=This file type does not support removing attributes.
+vfs.provider/get-attribute-not-supported.error=This file type does not support getting attributes.
+vfs.provider/write-not-supported.error=This file type cannot be written to.
+vfs.provider/get-type.error=Could not determine the type of file "{0}".
+vfs.provider/list-children-not-folder.error=Could not list the contents of "{0}" because it is not a folder.
+vfs.provider/list-children.error=Could not list the contents of folder "{0}".
+vfs.provider/delete-read-only.error=Could not delete "{0}" because it is read-only.
+vfs.provider/rename-read-only.error=Could not rename "{0}" because it is read-only.
+vfs.provider/rename-parent-read-only.error=Could not rename "{0}" because "{1}" is read-only.
+vfs.provider/rename-dest-exists.error=Destination "{0}" already existent.
+vfs.provider/delete.error=Could not delete "{0}".
+vfs.provider/rename.error=Could not rename "{0}" to "{1}".
+vfs.provider/create-folder-mismatched-type.error=Could not create folder "{0}" because it already exists and is a file.
+vfs.provider/create-folder-read-only.error=Could not create folder "{0}" because its parent folder is read-only.
+vfs.provider/create-folder.error=Could not create folder "{0}".
+vfs.provider/create-file.error=Could not create file "{0}".
+vfs.provider/write-read-only.error=Could not write to "{0}" because it is read-only.
+vfs.provider/write-not-file.error=Could not write to "{0}" because it is not a file.
+vfs.provider/write.error=Could not write to "{0}".
+vfs.provider/copy-file.error=Could not copy "{0}" to "{1}".
+vfs.provider/rename-filename.error=You can only rename within the same folder. Invalid Filename: "{0}".
+vfs.provider/copy-read-only.error=Could not copy {0} "{1}" to "{2}" because the destination file is read-only.
+vfs.provider/copy-missing-file.error=Could not copy "{0}" because it does not exist.
+vfs.provider/find-files.error=Could not find files in "{0}".
+vfs.provider/check-is-hidden.error=Could not determine if file "{0}" is hidden.
+vfs.provider/check-is-writeable.error=Could not determine if file "{0}" is writeable.
+vfs.provider/check-is-readable.error=Could not determine if file "{0}" is readable.
+vfs.provider/get-url.error=Could not create URL for "{0}".
+vfs.provider/resync.error=Could not resync "{0}".
+vfs.provider/close.error=Could not close "{0}".
+vfs.provider/read.error=Could not read file "{0}".
+vfs.provider/random-access.error=Could not read/write file "{0}".
+vfs.provider/read-not-readable.error=File "{0}" is not readable.
+vfs.provider/read-not-file.error=Could not read from "{0}" because it is a not a file.
+vfs.provider/closed.error=File closed.
+
+# DefaultFileContent
+vfs.provider/get-size-not-file.error=Could not determine the size of "{0}" because it is not a file.
+vfs.provider/get-size-write.error=Could not determine the size of file "{0}" because it is being written to.
+vfs.provider/get-size.error=Could not determine the size of file "{0}".
+vfs.provider/read-in-use.error=Could not read file "{0}" because it is currently being written to.
+vfs.provider/write-in-use.error=Could not write to "{0}" because it is currently in use.
+vfs.provider/random-in-use.error=Could not read/write file "{0}" because it is currently in use.
+vfs.provider/get-last-modified-writing.error=Could not determine the last modified timestamp of "{0}" because it is being written to.
+vfs.provider/get-last-modified-no-exist.error=Could not determine the last modified timestamp of "{0}" because it does not exist.
+vfs.provider/get-last-modified.error=Could not determine the last modified timestamp of "{0}".
+vfs.provider/set-last-modified-writing.error=Could not set the last modified timestamp of "{0}" because it is being written to.
+vfs.provider/set-last-modified-no-exist.error=Could not set the last modified timestamp of "{0}" because it does not exist.
+vfs.provider/set-last-modified.error=Could not set the last modified timestamp of "{0}".
+vfs.provider/get-certificates-no-exist.error=Could not retrieve the certificates of "{0}" because it does not exist.
+vfs.provider/get-certificates-writing.error=Could not retrieve the certificates of "{0}" because it is being written to.
+vfs.provider/get-certificates.error=Could not retrieve the certificates of "{0}".
+vfs.provider/close-instr.error=Could not close the input stream for file "{0}".
+vfs.provider/close-outstr.error=Could not close the output stream for file "{0}".
+vfs.provider/exists-attribute-no-exist.error=Could not check if attribute "{0}" of "{1}" exists because attributes are not supported.
+vfs.provider/get-attributes-no-exist.error=Could not get attributes for file "{0}" because it does not exist.
+vfs.provider/get-attributes.error=Could not get attributes "{0}".
+vfs.provider/set-attribute-no-exist.error=Could not set attribute "{0}" of "{1}" because it does not exist.
+vfs.provider/set-attribute.error=Could not set attribute "{0}" of "{1}".
+vfs.provider/remove-attribute-no-exist.error=Could not check if attribute "{0}" of "{1}" exists because attributes are not supported.
+vfs.provider/remove-attribute.error=Could not remove attribute "{0}" of "{1}".
+
+# AbstractFileSystemProvider
+vfs.provider/invalid-absolute-uri.error=Invalid absolute URI "{0}".
+vfs.provider/not-layered-fs.error=File system for URL scheme "{0}" is not a layered file system.
+vfs.provider/no-config-builder.error=File provider for URL scheme "{0}" do not provide a configuration builder.
+vfs.provider/config-key-invalid.error=The configuration builder for scheme "{0}" has no option "{1}".
+vfs.provider/config-value-invalid.error=The delegating configuration builder cant convert value "{2}" for key "{1}" scheme "{0}".
+vfs.provider/config-too-many-values.error=Too many values for configuration builder for scheme "{0}" key "{1}".
+vfs.provider/config-unexpected-primitive.error=Unexpected primitive "{0}".
+vfs.provider/config-unexpected-value-class.error=Cant convert a "{0}" value for scheme "{1}" key "{2}".
+
+# AbstractFileSystem
+vfs.provider/files-cache-missing.error=No files-cache implementation set.
+vfs.provider/mismatched-fs-for-name.error=Incorrect file system URI "{2}" in name "{0}", was expecting "{1}".
+vfs.provider/junctions-not-supported.error=Junctions not supported for file system "{0}".
+vfs.provider/notify-listener.warn=Could not notify listener of change to "{0}".
+vfs.provider/replicate-missing-file.error=Could not replicate "{0}" as it does not exist.
+vfs.provider/replicate-file.error=Could not replicate "{0}".
+vfs.provider/resolve-file.error=Could not resolve file "{0}".
+
+# AbstractFileProvider
+vfs.provider/filename-parser-missing.error=No filename-parser implementation set.
+
+# AbstractFileName
+vfs.provider/filename-type.error=A filename can only be of type FileType.FOLDER or FileType.FILE
+
+# Operations
+vfs.operation/wrong-type.error=Can't lookup operation, wrong type: "{0}"
+vfs.operation/not-found.error=Operation not found, type: "{0}"
+vfs.operation/cant-register.error=Can't register operation, wrong type: "{0}"
+vfs.operation/operation-not-supported.error=Operation "{0}" not supported.
+vfs.operation/operation-provider-already-added.error=Operation provider already added to scheme "{0}"
+
+# RandomAccess
+vfs.provider/random-access-invalid-position.error=Invalid position: "{0}"
+vfs.provider/random-access-open-failed.error=Could not access file "{0}" because it does not exist.
+
+# UriParser
+vfs.provider/missing-double-slashes.error=Expecting // to follow the scheme in URI "{0}".
+vfs.provider/missing-hostname.error=Hostname missing from URI "{0}".
+vfs.provider/missing-port.error=Port number is missing from URI "{0}".
+vfs.provider/missing-hostname-path-sep.error=Expecting / to follow the hostname in URI "{0}".
+vfs.provider/invalid-descendent-name.error=Invalid descendent file name "{0}".
+vfs.provider/invalid-escape-sequence.error=Invalid URI escape sequence "{0}".
+vfs.provider/invalid-relative-path.error=Invalid relative file name.
+
+# DefaultFileSystemManager
+vfs.impl/unknown-scheme.error=Unknown scheme "{0}" in URI "{1}".
+vfs.impl/find-rel-file.error=Could not find file with URI "{0}" because it is a relative path, and no base URI was provided.
+vfs.impl/multiple-providers-for-scheme.error=Multiple providers registered for URL scheme "{0}".
+vfs.impl/configuration-already-set.error=FilesCache implementation already set.
+vfs.impl/configuration-already-in-use.error=The configuration is already attached to an filesystemmanager. You cant change it anymore.
+vfs.impl/unknown-provider.error=No file provider is registered with URI scheme "{0}" to handle file "{1}".
+vfs.impl/no-provider-for-file.error=Could not find a file provider that can handle file "{0}".
+vfs.impl/no-local-file-provider.error=Could not find a file provider which can handle local files.
+vfs.impl/no-replicator.error=No file replicator configured.
+vfs.impl/no-temp-file-store.error=No temporary file store configured.
+vfs.impl/replicate-file.error=Could not replicate "{0}".
+vfs.impl/delete-temp.warn=Could not clean up temporary file "{0}".
+vfs.impl/init-replicator.error=Could not initialise file replicator.
+vfs.impl/already-inited.error=Manager already inited, cant change the configuration now.
+vfs.impl/invalid-decorator.error="{0}" is not a valid decorator. It has to extend "DecoratedFileObject" and must provide a single argument constructor which takes a "FileObject"
+vfs.impl/temp-dir.info=Using "{0}" as temporary files store.
+
+# StandardFileSystemManager
+vfs.impl/find-config-file.error=Could not find VFS configuration resource "{0}".
+vfs.impl/load-config.error=Could not load VFS configuration from "{0}".
+vfs.impl/create-provider.error=Could not create file provider of class "{0}".
+vfs.impl/create-files-cache.error=Could not create files-cache implementation of class "{0}".
+vfs.impl/create-client-factory.error=Could not create client factory of class "{0}".
+vfs.impl/skipping-provider.debug=Skipping provider "{0}" because required class "{1}" is not available.
+vfs.impl/skipping-provider-scheme.debug=Skipping provider "{0}" because required scheme "{1}" is not available.
+
+# FileTypeMap
+vfs.impl/multiple-schemes.error=This file requires multiple schemes. Use getSchemes() instead.
+
+# VFSClassLoader
+vfs.impl/pkg-sealing-unsealed=Trying to seal package "{0}" that exists as unsealed.
+vfs.impl/pkg-sealed-other-url=Package "{0}" exists and is sealed with other URL.
+
+# VirtualFileSystem
+vfs.impl/nested-junction.error=Attempting to create a nested junction at "{0}".  Nested junctions are not supported.
+vfs.impl/create-junction.error=Could not create a junction at "{0}".
+
+# SoftRefFilesCache
+vfs.impl/SoftRefReleaseThread-interrupt.info=SoftRefFilesCache - Release Thread interrupted.
+vfs.impl/SoftRefReleaseThread-already-running.warn=SoftRefFilesCache - Release Thread already running.
+
+# Local Provider
+vfs.provider.local/get-type.error=Could not determine the type of "{0}".
+vfs.provider.local/delete-file.error=Could not delete "{0}".
+vfs.provider.local/rename-file.error=Could not rename file "{0}" to "{1}".
+vfs.provider.local/create-folder.error=Could not create directory "{0}".
+vfs.provider.local/not-absolute-file-name.error=URI "{0}" is not an absolute file name.
+vfs.provider.local/missing-share-name.error=Share name missing from UNC file name "{0}".
+
+# Temp Provider
+vfs.provider.temp/get-type.error=Could not determine the type of "{0}".
+vfs.provider.temp/delete-file.error=Could not delete "{0}".
+vfs.provider.temp/rename-file.error=Could not rename file "{0}" to "{1}".
+vfs.provider.temp/create-folder.error=Could not create directory "{0}".
+vfs.provider.temp/not-absolute-file-name.error=URI "{0}" is not an absolute file name.
+vfs.provider.temp/missing-share-name.error=Share name missing from UNC file name "{0}".
+
+# SMB Provider
+vfs.provider.smb/missing-share-name.error=The share name is missing from URI "{0}".
+vfs.provider.smb/get-type.error=Could not detemine the type of "{0}".
+
+# Zip Provider
+vfs.provider.zip/open-zip-file.error=Could not open Zip file "{0}".
+vfs.provider.zip/close-zip-file.error=Could not close Zip file "{0}".
+
+# Bzip2 Provider
+vfs.provider.bzip2/not-a-bzip2-file.error=File "{0}" is not bzip2 compressed.
+
+# JarFileSystem
+vfs.provider.jar/open-jar-file.error=Could not open Jar file "{0}".
+
+# JarURLConnectionImpl
+vfs.provider.jar/jar-file-no-access.error=JarURLConnections in VFS does not give access to the JarFile.
+vfs.provider.jar/jar-entry-no-access.error=JarURLConnections in VFS does not give access to the JarEntry.
+
+# FTP Provider
+vfs.provider.ftp/get-type.error=Could not determine the file type of "{0}".
+vfs.provider.ftp/delete-file.error=Could not delete FTP file "{0}".
+vfs.provider.ftp/rename-file.error=Could not rename FTP file "{0}" to "{1}".
+vfs.provider.ftp/create-folder.error=Could not create FTP directory "{0}".
+vfs.provider.ftp/finish-get.error=Could not get FTP file "{0}".
+vfs.provider.ftp/finish-put.error=Could not put FTP file "{0}".
+vfs.provider.ftp/connect-rejected.error=Connection to FTP server on "{0}" rejected.
+vfs.provider.ftp/login.error=Could not login to FTP server on "{0}" as user "{1}".
+vfs.provider.ftp/set-binary.error=Could not switch to binary transfer mode.
+vfs.provider.ftp/connect.error=Could not connect to FTP server on "{0}".
+vfs.provider.ftp/close-connection.error=Could not close connection to FTP server.
+vfs.provider.ftp/change-work-directory.error=Could not change to work directory "{0}".
+vfs.provider.ftp/invalid-directory-entry.debug=Invalid directory entry at line "{0}" (directory "{1}").
+vfs.provider.ftp/output-error.debug=Cant open output connection for file "{0}". Reason: "{1}".
+vfs.provider.ftp/input-error.debug=Cant open input connection for file "{0}". Reason: "{1}".
+vfs.provider.ftp.wrapper/change-work-directory-back.error=Could not change back to work directory "{0}".
+
+# URL Provider
+vfs.provider.url/badly-formed-uri.error=Badly formed URI "{0}".
+
+# Http Provider
+vfs.provider.http/get.error=GET method failed for "{0}".
+vfs.provider.http/head.error=HEAD method failed for "{0}".
+vfs.provider.http/last-modified.error=No Last-Modified header in HTTP response.
+vfs.provider.http/get-range.error=GET method failed for "{0}" range "{1}-".
+vfs.provider.http/connect.error=Could not connect to HTTP server on "{0}".
+
+# WebDAV Provider
+vfs.provider.webdav/write-file.error=Write to file failed with message: "{0}".
+vfs.provider.webdav/list-children.error=List child resources failed with message: "{0}".
+vfs.provider.webdav/create-collection.error=Create collection failed with message: "{0}".
+vfs.provider.webdav/delete-file.error=Delete file failed with message: "{0}".
+vfs.provider.webdav/create-client.error=Could not create client for server "{0}".
+vfs.provider.webdav/rename-file.error=Rename file failed with message: "{0}".
+
+# SFTP Provider
+vfs.provider.sftp/connect.error=Could not connect to SFTP server at "{0}".
+vfs.provider.sftp/change-work-directory.error=Could not change to work directory "{0}".
+vfs.provider.sftp/unknown-permissions.error=File permissions not fetched.
+vfs.provider.sftp/unknown-size.error=File size not fetched.
+vfs.provider.sftp/create-folder.error=Folder creation failed with unknown error.
+vfs.provider.sftp/delete.error=Delete failed with unknown error.
+vfs.provider.sftp/list-children.error=List folder contents failed with unknown error.
+vfs.provider.sftp/put-file.error=Write file contents failed with unknown error.
+vfs.provider.sftp/get-file.error=Read file contents failed with unknown error.
+vfs.provider.sftp/load-private-key.error=Could not load private key from "{0}".
+vfs.provider.sftp/config-sshdir.error=SSH-Folder "{0}" non existent or not a folder.
+vfs.provider.sftp/unknown-modtime.error=Last modification time not fetched.
+vfs.provider.sftp/known-hosts.error=Error during processing known-hosts file "{0}".
+vfs.provider.sftp/StrictHostKeyChecking-arg.error=Illegal argument "{0}" hostKeyChecking can only be "ask", "yes" or "no"
+vfs.provider.sftp/change-work-directory-back.error=Could not change back to work directory "{0}".
+
+# Ant tasks
+vfs.tasks/sync.no-destination.error=No destination file or directory specified.
+vfs.tasks/sync.too-many-destinations.error=Cannot specify both a destination file and a destination directory.
+vfs.tasks/sync.no-source-files.warn=No source files specified.
+vfs.tasks/sync.no-source-file.error=No source file specified.
+vfs.tasks/sync.too-many-source-files.error=Too many source files specified.
+vfs.tasks/sync.source-not-file.error=Source file "{0}" is not a file, or does not exist.
+vfs.tasks/sync.src-file-no-exist.warn=Source file "{0}" does not exist.
+vfs.tasks/sync.duplicate-source-files.warn=Multiple source files for destination file "{0}".
+vfs.tasks/delete.no-source-files.error=No files to delete specified.
+vfs.tasks/mkdir.create-folder.info=Creating directory "{0}".
+
+# Selectors
+vfs.selectors/filefilter.missing.error=Configure a fileFilter or override accept();
+
+# Utils
+vfs.util/find-abstract-file-object.error=Object didnt extend from AbstractFileObject. Object "{0}"
+vfs.util/missing-capability.error=The Filesystem do not provide the required capability "{0}"
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Selectors.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Selectors.java
new file mode 100644
index 0000000..24c0423
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/Selectors.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * Several standard file selectors.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class Selectors
+{
+    /**
+     * A {@link FileSelector} that selects only the base file/folder.
+     */
+    public static final FileSelector SELECT_SELF = new FileDepthSelector(0, 0);
+
+    /**
+     * A {@link FileSelector} that selects the base file/folder and its
+     * direct children.
+     */
+    public static final FileSelector SELECT_SELF_AND_CHILDREN = new FileDepthSelector(0, 1);
+
+    /**
+     * A {@link FileSelector} that selects only the direct children
+     * of the base folder.
+     */
+    public static final FileSelector SELECT_CHILDREN = new FileDepthSelector(1, 1);
+
+    /**
+     * A {@link FileSelector} that selects all the descendents of the
+     * base folder, but does not select the base folder itself.
+     */
+    public static final FileSelector EXCLUDE_SELF = new FileDepthSelector(1, Integer.MAX_VALUE);
+
+    /**
+     * A {@link FileSelector} that only files (not folders).
+     */
+    public static final FileSelector SELECT_FILES = new FileTypeSelector(FileType.FILE);
+
+    /**
+     * A {@link FileSelector} that only folders (not files).
+     */
+    public static final FileSelector SELECT_FOLDERS = new FileTypeSelector(FileType.FOLDER);
+
+    /**
+     * A {@link FileSelector} that selects the base file/folder, plus all
+     * its descendents.
+     */
+    public static final FileSelector SELECT_ALL = new AllFileSelector();
+
+    /**
+     * Prevent the class from being instantiated.
+     */
+    private Selectors()
+    {
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticationData.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticationData.java
new file mode 100644
index 0000000..b3ec51d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticationData.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.Iterator;
+
+/**
+ * Container for various authentication data.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class UserAuthenticationData
+{
+    /**
+     * Inner class to represent portions of the user authentication data.
+     */
+    public static class Type implements Comparable
+    {
+        /** The type name */
+        private final String type;
+
+        public Type(String type)
+        {
+            this.type = type;
+        }
+
+        public boolean equals(Object o)
+        {
+            if (this == o)
+            {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass())
+            {
+                return false;
+            }
+
+            Type type1 = (Type) o;
+
+            if (type != null ? !type.equals(type1.type) : type1.type != null)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public int compareTo(Object o)
+        {
+            Type t = (Type) o;
+
+            return type.compareTo(t.type);
+        }
+
+        public int hashCode()
+        {
+            return type != null ? type.hashCode() : 0;
+        }
+
+        public String toString()
+        {
+            return type;
+        }
+    }
+
+    /** The user name. */
+    public static final Type USERNAME = new Type("username");
+
+    /** The password. */
+    public static final Type PASSWORD = new Type("password");
+
+    /** The user's domain. */
+    public static final Type DOMAIN = new Type("domain");
+
+    /** The authentication data. */
+    private final Map authenticationData = new TreeMap();
+
+    public UserAuthenticationData()
+    {
+    }
+
+    /**
+     * set a data to this collection.
+     * @param type The Type to add
+     * @param data The data associated with the Type
+     */
+    public void setData(Type type, char[] data)
+    {
+        authenticationData.put(type, data);
+    }
+
+    /**
+     * get a data from the collection.
+     * @param type The Type to retrieve.
+     * @return a character array containing the data associated with the type.
+     */
+    public char[] getData(Type type)
+    {
+        return (char[]) authenticationData.get(type);
+    }
+
+    /**
+     * deleted all data stored within this authenticator.
+     */
+    public void cleanup()
+    {
+        // step 1: nullify character buffers
+        Iterator iterAuthenticationData = authenticationData.values().iterator();
+        while (iterAuthenticationData.hasNext())
+        {
+            char[] data = (char[]) iterAuthenticationData.next();
+            if (data == null || data.length < 0)
+            {
+                continue;
+            }
+
+            for (int i = 0; i < data.length; i++)
+            {
+                data[i] = 0;
+            }
+        }
+        // step 2: allow data itself to gc
+        authenticationData.clear();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticator.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticator.java
new file mode 100644
index 0000000..dd4f82d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/UserAuthenticator.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+/**
+ * The user authenticator is used to query credentials from the user. Since a UserAuthenticator
+ * is provided with the {@link FileSystemOptions} to a {@link FileSystem} it should also implement
+ * reasonable equals and hashCode functions if the FileSystem should be shared.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public interface UserAuthenticator
+{
+    /**
+     * Queries the given type from the user.
+     * @param types An array containing the user's credentials
+     * @return The UserAuthenticationData.
+     */
+    UserAuthenticationData requestAuthentication(UserAuthenticationData.Type[] types);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VFS.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VFS.java
new file mode 100644
index 0000000..da78147
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VFS.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * The main entry point for the VFS.  Used to create {@link FileSystemManager}
+ * instances.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class VFS
+{
+    /** The URI style */
+    private static Boolean uriStyle;
+
+    /** The FileSystemManager */
+    private static FileSystemManager instance;
+
+    private VFS()
+    {
+    }
+
+    /**
+     * Returns the default {@link FileSystemManager} instance.
+     * @return The FileSystemManager.
+     * @throws FileSystemException if an error occurs creating the manager.
+     */
+    public static synchronized FileSystemManager getManager()
+        throws FileSystemException
+    {
+        if (instance == null)
+        {
+            instance = createManager("org.apache.commons.vfs.impl.StandardFileSystemManager");
+        }
+        return instance;
+    }
+
+    /**
+     * Creates a file system manager instance.
+     * @param managerClassName The specific manager impelmentation class name.
+     * @return The FileSystemManager.
+     * @throws FileSystemException if an error occurs creating the manager.
+     */
+    private static FileSystemManager createManager(final String managerClassName)
+        throws FileSystemException
+    {
+        try
+        {
+            // Create instance
+            final Class mgrClass = Class.forName(managerClassName);
+            final FileSystemManager mgr = (FileSystemManager) mgrClass.newInstance();
+
+            /*
+            try
+            {
+                // Set the logger
+                final Method setLogMethod = mgrClass.getMethod("setLogger", new Class[]{Log.class});
+                final Log logger = LogFactory.getLog(VFS.class);
+                setLogMethod.invoke(mgr, new Object[]{logger});
+            }
+            catch (final NoSuchMethodException e)
+            {
+                // Ignore; don't set the logger
+            }
+            */
+
+            try
+            {
+                // Initialise
+                final Method initMethod = mgrClass.getMethod("init", (Class[]) null);
+                initMethod.invoke(mgr, (Object[]) null);
+            }
+            catch (final NoSuchMethodException e)
+            {
+                // Ignore; don't initialize
+            }
+
+            return mgr;
+        }
+        catch (final InvocationTargetException e)
+        {
+            throw new FileSystemException("vfs/create-manager.error",
+                managerClassName,
+                e.getTargetException());
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs/create-manager.error",
+                managerClassName,
+                e);
+        }
+    }
+
+    public static boolean isUriStyle()
+    {
+        if (uriStyle == null)
+        {
+            uriStyle = Boolean.FALSE;
+        }
+        return uriStyle.booleanValue();
+    }
+
+    public static void setUriStyle(boolean uriStyle)
+    {
+        if (VFS.uriStyle != null && VFS.uriStyle.booleanValue() != uriStyle)
+        {
+            throw new IllegalStateException("URI STYLE ALREADY SET TO");
+        }
+        VFS.uriStyle = uriStyle ? Boolean.TRUE : Boolean.FALSE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VfsLog.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VfsLog.java
new file mode 100644
index 0000000..f13d809
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/VfsLog.java
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import org.apache.commons.logging.Log;
+
+/**
+ * This class is to keep the old logging behaviour (for ant-task) and to be able to
+ * correctly use commons-logging.<br>
+ * I hope i could remove it sometimes.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class VfsLog
+{
+    // static utility class
+    private VfsLog()
+    {
+    }
+
+    /**
+     * warning.
+     * @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(Log vfslog, Log commonslog, String message, Throwable t)
+    {
+        if (vfslog != null)
+        {
+            vfslog.warn(message, t);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.warn(message, t);
+        }
+    }
+
+    /**
+     * warning.
+     * @param vfslog The base component Logger to use.
+     * @param commonslog The class specific Logger
+     * @param message The message to log.
+     */
+    public static void warn(Log vfslog, Log commonslog, String message)
+    {
+        if (vfslog != null)
+        {
+            vfslog.warn(message);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.warn(message);
+        }
+    }
+
+    /**
+     * debug.
+     * @param vfslog The base component Logger to use.
+     * @param commonslog The class specific Logger
+     * @param message The message to log.
+     */
+    public static void debug(Log vfslog, Log commonslog, String message)
+    {
+        if (vfslog != null)
+        {
+            vfslog.debug(message);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.debug(message);
+        }
+    }
+
+    /**
+     * 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 debug(Log vfslog, Log commonslog, String message, Throwable t)
+    {
+        if (vfslog != null)
+        {
+            vfslog.debug(message, t);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.debug(message, t);
+        }
+    }
+
+    /**
+     * 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 info(Log vfslog, Log commonslog, String message, Throwable t)
+    {
+        if (vfslog != null)
+        {
+            vfslog.info(message, t);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.info(message, t);
+        }
+    }
+
+    /**
+     * info.
+     * @param vfslog The base component Logger to use.
+     * @param commonslog The class specific Logger
+     * @param message The message to log.
+     */
+    public static void info(Log vfslog, Log commonslog, String message)
+    {
+        if (vfslog != null)
+        {
+            vfslog.info(message);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.info(message);
+        }
+    }
+
+    /**
+     * 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 error(Log vfslog, Log commonslog, String message, Throwable t)
+    {
+        if (vfslog != null)
+        {
+            vfslog.error(message, t);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.error(message, t);
+        }
+    }
+
+    /**
+     * error.
+     * @param vfslog The base component Logger to use.
+     * @param commonslog The class specific Logger
+     * @param message The message to log.
+     */
+    public static void error(Log vfslog, Log commonslog, String message)
+    {
+        if (vfslog != null)
+        {
+            vfslog.error(message);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.error(message);
+        }
+    }
+
+    /**
+     * 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 fatal(Log vfslog, Log commonslog, String message, Throwable t)
+    {
+        if (vfslog != null)
+        {
+            vfslog.fatal(message, t);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.fatal(message, t);
+        }
+    }
+
+    /**
+     * fatal.
+     * @param vfslog The base component Logger to use.
+     * @param commonslog The class specific Logger
+     * @param message The message to log.
+     */
+    public static void fatal(Log vfslog, Log commonslog, String message)
+    {
+        if (vfslog != null)
+        {
+            vfslog.fatal(message);
+        }
+        else if (commonslog != null)
+        {
+            commonslog.fatal(message);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/StaticUserAuthenticator.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/StaticUserAuthenticator.java
new file mode 100644
index 0000000..193003d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/StaticUserAuthenticator.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.auth;
+
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+/**
+ * Provides always the same credentials data passed in with the constructor.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class StaticUserAuthenticator implements UserAuthenticator, Comparable
+{
+    /** The user name */
+    private final String username;
+
+    /** The password */
+    private final String password;
+
+    /** The user's domain */
+    private final String domain;
+
+    public StaticUserAuthenticator(String domain, String username, String password)
+    {
+        this.username = username;
+        this.password = password;
+        this.domain = domain;
+    }
+
+    public UserAuthenticationData requestAuthentication(UserAuthenticationData.Type[] types)
+    {
+        UserAuthenticationData data = new UserAuthenticationData();
+        data.setData(UserAuthenticationData.DOMAIN, UserAuthenticatorUtils.toChar(domain));
+        data.setData(UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(username));
+        data.setData(UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(password));
+        return data;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    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;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+        {
+            return true;
+        }
+
+        if (obj == null)
+        {
+            return false;
+        }
+
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+
+        StaticUserAuthenticator other = (StaticUserAuthenticator) obj;
+        return equalsNullsafe(domain, other.domain)
+                && equalsNullsafe(username, other.username)
+                && equalsNullsafe(password, other.password);
+    }
+
+    private boolean equalsNullsafe(final String thisString, final String otherString)
+    {
+        if (thisString == null)
+        {
+            if (otherString != null)
+            {
+                return false;
+            }
+        }
+        else if (!thisString.equals(otherString))
+        {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int compareTo(final Object o)
+    {
+        StaticUserAuthenticator other = (StaticUserAuthenticator) o;
+        int result = compareStringOrNull(domain, other.domain);
+        result = result == 0 ? compareStringOrNull(username, other.username) : result;
+        result = result == 0 ? compareStringOrNull(password, other.password) : result;
+
+        return result;
+    }
+
+    private int compareStringOrNull(final String thisString, final String otherString)
+    {
+        if (thisString == null)
+        {
+            if (otherString != null)
+            {
+                return -1;
+            }
+        }
+        else
+        {
+            if (otherString == null)
+            {
+                return 1;
+            }
+
+            final int result = thisString.compareTo(otherString);
+            if (result != 0)
+            {
+                return result;
+            }
+        }
+
+        return 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String toString()
+    {
+        StringBuffer buffer = new StringBuffer();
+        if (domain != null)
+        {
+            buffer.append(domain).append('\\');
+        }
+        if (username != null)
+        {
+            buffer.append(username);
+        }
+        else
+        {
+            buffer.append("(null)");
+        }
+        if (password != null)
+        {
+            buffer.append(":***");
+        }
+        return buffer.toString();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/package.html
new file mode 100644
index 0000000..754cf02
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/auth/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>VFS Authentication implementation</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/AbstractFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/AbstractFilesCache.java
new file mode 100644
index 0000000..dfc4f41
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/AbstractFilesCache.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.provider.AbstractVfsComponent;
+
+/**
+ * Description.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractFilesCache extends AbstractVfsComponent implements FilesCache
+{
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/DefaultFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/DefaultFilesCache.java
new file mode 100644
index 0000000..c5db274
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/DefaultFilesCache.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link org.apache.commons.vfs.FilesCache} implementation.<br>
+ * This implementation caches every file for the complete lifetime of the used
+ * {@link org.apache.commons.vfs.FileSystemManager}.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultFilesCache extends AbstractFilesCache
+{
+
+    /** The FileSystem cache */
+    private final Map filesystemCache = new HashMap(10);
+
+    public void putFile(final FileObject file)
+    {
+        Map files = getOrCreateFilesystemCache(file.getFileSystem());
+        files.put(file.getName(), file);
+    }
+
+    public FileObject getFile(final FileSystem filesystem, final FileName name)
+    {
+        Map files = getOrCreateFilesystemCache(filesystem);
+        return (FileObject) files.get(name);
+    }
+
+    public void clear(FileSystem filesystem)
+    {
+        Map files = getOrCreateFilesystemCache(filesystem);
+        files.clear();
+    }
+
+    protected Map getOrCreateFilesystemCache(FileSystem filesystem)
+    {
+        Map files = (Map) filesystemCache.get(filesystem);
+        if (files == null)
+        {
+            files = new HashMap();
+            filesystemCache.put(filesystem, files);
+        }
+
+        return files;
+    }
+
+    public void close()
+    {
+        super.close();
+
+        filesystemCache.clear();
+    }
+
+    public void removeFile(FileSystem filesystem, FileName name)
+    {
+        Map files = getOrCreateFilesystemCache(filesystem);
+        files.remove(name);
+    }
+
+    public void touchFile(FileObject file)
+    {
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/FileSystemAndNameKey.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/FileSystemAndNameKey.java
new file mode 100644
index 0000000..e0b7b87
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/FileSystemAndNameKey.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+
+/**
+ * Key for various cache implementations.<br>
+ * It compares the fileSystem (by hashCode) and the filename.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+class FileSystemAndNameKey implements Comparable
+{
+    /** The FileSystem */
+    private final FileSystem fileSystem;
+
+    /** The FileName */
+    private final FileName fileName;
+
+    /** hashcode to identify this object */
+    private final int fileSystemId;
+
+    FileSystemAndNameKey(final FileSystem fileSystem, final FileName fileName)
+    {
+        this.fileSystem = fileSystem;
+        this.fileSystemId = System.identityHashCode(fileSystem);
+
+        this.fileName = fileName;
+    }
+
+    public int compareTo(Object o)
+    {
+        FileSystemAndNameKey other = (FileSystemAndNameKey) o;
+
+        if (fileSystemId < other.fileSystemId)
+        {
+            return -1;
+        }
+        if (fileSystemId > other.fileSystemId)
+        {
+            return 1;
+        }
+
+        return fileName.compareTo(other.fileName);
+    }
+
+    FileSystem getFileSystem()
+    {
+        return fileSystem;
+    }
+
+    FileName getFileName()
+    {
+        return fileName;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/LRUFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/LRUFilesCache.java
new file mode 100644
index 0000000..c35a9b8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/LRUFilesCache.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.collections.map.AbstractLinkedMap;
+import org.apache.commons.collections.map.LRUMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.util.Messages;
+
+/**
+ * This implementation caches every file using {@link LRUMap}.<br>
+ * The default constructor uses a LRU size of 100 per filesystem.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class LRUFilesCache extends AbstractFilesCache
+{
+    /** The default LRU size */
+    private static final int DEFAULT_LRU_SIZE = 100;
+    /**
+     * The logger to use.
+     */
+    private final Log log = LogFactory.getLog(LRUFilesCache.class);
+
+    /** The FileSystem cache */
+    private final Map filesystemCache = new HashMap(10);
+
+    /** The size of the cache */
+    private final int lruSize;
+
+    /**
+     * The file cache
+     */
+    private class MyLRUMap extends LRUMap
+    {
+        /** The FileSystem */
+        private final FileSystem filesystem;
+
+        public MyLRUMap(final FileSystem filesystem, int size)
+        {
+            super(size, true);
+            this.filesystem = filesystem;
+        }
+
+        protected boolean removeLRU(final AbstractLinkedMap.LinkEntry linkEntry)
+        {
+            synchronized (LRUFilesCache.this)
+            {
+                FileObject file = (FileObject) linkEntry.getValue();
+
+                // System.err.println(">>> " + size() + " check removeLRU:" + linkEntry.getKey().toString());
+
+                if (file.isAttached() || file.isContentOpen())
+                {
+                    // do not allow open or attached files to be removed
+                    // System.err.println(">>> " + size() + " VETO removeLRU:" +
+                    //    linkEntry.getKey().toString() + " (" + file.isAttached() + "/" +
+                    //    file.isContentOpen() + ")");
+                    return false;
+                }
+
+                // System.err.println(">>> " + size() + " removeLRU:" + linkEntry.getKey().toString());
+                if (super.removeLRU(linkEntry))
+                {
+                    try
+                    {
+                        // force detach
+                        file.close();
+                    }
+                    catch (FileSystemException e)
+                    {
+                        VfsLog.warn(getLogger(), log, Messages.getString("vfs.impl/LRUFilesCache-remove-ex.warn"), e);
+                    }
+
+                    Map files = (Map) filesystemCache.get(filesystem);
+                    if (files.size() < 1)
+                    {
+                        filesystemCache.remove(filesystem);
+                    }
+
+                    return true;
+                }
+
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Default constructor. Uses a LRU size of 100 per filesystem.
+     */
+    public LRUFilesCache()
+    {
+        this(DEFAULT_LRU_SIZE);
+    }
+
+    /**
+     * Set the desired LRU size.
+     *
+     * @param lruSize the LRU size
+     */
+    public LRUFilesCache(int lruSize)
+    {
+        this.lruSize = lruSize;
+    }
+
+    public void putFile(final FileObject file)
+    {
+        synchronized (this)
+        {
+            Map files = getOrCreateFilesystemCache(file.getFileSystem());
+
+            // System.err.println(">>> " + files.size() + " put:" + file.toString());
+
+            files.put(file.getName(), file);
+        }
+    }
+
+    public FileObject getFile(final FileSystem filesystem, final FileName name)
+    {
+        synchronized (this)
+        {
+            Map files = getOrCreateFilesystemCache(filesystem);
+
+            // FileObject fo = (FileObject) files.get(name);
+            // System.err.println(">>> " + files.size() + " get:" + name.toString() + " " + fo);
+
+            return (FileObject) files.get(name);
+        }
+    }
+
+    public void clear(final FileSystem filesystem)
+    {
+        synchronized (this)
+        {
+            // System.err.println(">>> clear fs " + filesystem);
+
+            Map files = getOrCreateFilesystemCache(filesystem);
+            files.clear();
+
+            filesystemCache.remove(filesystem);
+        }
+    }
+
+    protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
+    {
+        Map files = (Map) filesystemCache.get(filesystem);
+        if (files == null)
+        {
+            // System.err.println(">>> create fs " + filesystem);
+
+            files = new MyLRUMap(filesystem, lruSize);
+            filesystemCache.put(filesystem, files);
+        }
+
+        return files;
+    }
+
+    public void close()
+    {
+        super.close();
+
+        synchronized (this)
+        {
+            // System.err.println(">>> clear all");
+
+            filesystemCache.clear();
+        }
+    }
+
+    public void removeFile(final FileSystem filesystem, final FileName name)
+    {
+        synchronized (this)
+        {
+            Map files = getOrCreateFilesystemCache(filesystem);
+
+            // System.err.println(">>> " + files.size() + " remove:" + name.toString());
+
+            files.remove(name);
+
+            if (files.size() < 1)
+            {
+                filesystemCache.remove(filesystem);
+            }
+        }
+    }
+
+    public void touchFile(final FileObject file)
+    {
+        // this moves the file back on top
+        getFile(file.getFileSystem(), file.getName());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/NullFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/NullFilesCache.java
new file mode 100644
index 0000000..4205c4a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/NullFilesCache.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+
+/**
+ * <p>
+ * A {@link org.apache.commons.vfs.FilesCache} implementation.<br>
+ * This implementation never ever caches a single file.
+ * </p>
+ * <p>
+ * <b>Notice: if you use resolveFile(uri) multiple times with the same path, the system will always
+ * create a new instance.
+ * Changes on one instance of this file are not seen by the others.</b>
+ * </p>
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class NullFilesCache extends AbstractFilesCache
+{
+    public void putFile(final FileObject file)
+    {
+    }
+
+    public FileObject getFile(final FileSystem filesystem, final FileName name)
+    {
+        return null;
+    }
+
+    public void clear(FileSystem filesystem)
+    {
+    }
+
+    public void close()
+    {
+        super.close();
+    }
+
+    public void removeFile(FileSystem filesystem, FileName name)
+    {
+    }
+
+    public void touchFile(FileObject file)
+    {
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/OnCallRefreshFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/OnCallRefreshFileObject.java
new file mode 100644
index 0000000..7757fd8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/OnCallRefreshFileObject.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import java.util.List;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.impl.DecoratedFileObject;
+
+/**
+ * This decorator refreshes the fileObject data on every call.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class OnCallRefreshFileObject extends DecoratedFileObject
+{
+    public OnCallRefreshFileObject(FileObject fileObject)
+    {
+        super(fileObject);
+    }
+
+    public void close() throws FileSystemException
+    {
+        refresh();
+        super.close();
+    }
+
+    public void copyFrom(FileObject srcFile, FileSelector selector) throws FileSystemException
+    {
+        refresh();
+        super.copyFrom(srcFile, selector);
+    }
+
+    public void createFile() throws FileSystemException
+    {
+        refresh();
+        super.createFile();
+    }
+
+    public void createFolder() throws FileSystemException
+    {
+        refresh();
+        super.createFolder();
+    }
+
+    public boolean delete() throws FileSystemException
+    {
+        refresh();
+        return super.delete();
+    }
+
+    public int delete(FileSelector selector) throws FileSystemException
+    {
+        refresh();
+        return super.delete(selector);
+    }
+
+    public boolean exists() throws FileSystemException
+    {
+        refresh();
+        return super.exists();
+    }
+
+    public void findFiles(FileSelector selector, boolean depthwise, List selected) throws FileSystemException
+    {
+        refresh();
+        super.findFiles(selector, depthwise, selected);
+    }
+
+    public FileObject[] findFiles(FileSelector selector) throws FileSystemException
+    {
+        refresh();
+        return super.findFiles(selector);
+    }
+
+    public FileObject getChild(String name) throws FileSystemException
+    {
+        refresh();
+        return super.getChild(name);
+    }
+
+    public FileObject[] getChildren() throws FileSystemException
+    {
+        refresh();
+        return super.getChildren();
+    }
+
+    public FileContent getContent() throws FileSystemException
+    {
+        refresh();
+        return super.getContent();
+    }
+
+    public FileType getType() throws FileSystemException
+    {
+        refresh();
+        return super.getType();
+    }
+
+    public boolean isHidden() throws FileSystemException
+    {
+        refresh();
+        return super.isHidden();
+    }
+
+    public boolean isReadable() throws FileSystemException
+    {
+        refresh();
+        return super.isReadable();
+    }
+
+    public boolean isWriteable() throws FileSystemException
+    {
+        refresh();
+        return super.isWriteable();
+    }
+
+    public void moveTo(FileObject destFile) throws FileSystemException
+    {
+        refresh();
+        super.moveTo(destFile);
+    }
+
+    public FileObject resolveFile(String name, NameScope scope) throws FileSystemException
+    {
+        refresh();
+        return super.resolveFile(name, scope);
+    }
+
+    public FileObject resolveFile(String path) throws FileSystemException
+    {
+        refresh();
+        return super.resolveFile(path);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java
new file mode 100644
index 0000000..fcfd00b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/SoftRefFilesCache.java
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.util.Messages;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * This implementation caches every file as long as it is strongly reachable by
+ * the java vm. As soon as the vm needs memory - every softly reachable file
+ * will be discarded.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date: 2005-09-30 09:02:41 +0200 (Fr, 30 Sep
+ *          2005) $
+ * @see SoftReference
+ */
+public class SoftRefFilesCache extends AbstractFilesCache
+{
+    private static final int TIMEOUT = 1000;
+    /**
+     * The logger to use.
+     */
+    private final Log log = LogFactory.getLog(SoftRefFilesCache.class);
+
+    private final Map filesystemCache = new HashMap();
+    private final Map refReverseMap = new HashMap(100);
+    private final ReferenceQueue refqueue = new ReferenceQueue();
+
+    private SoftRefReleaseThread softRefReleaseThread;
+
+    /**
+     * This thread will listen on the ReferenceQueue and remove the entry in the
+     * filescache as soon as the vm removes the reference
+     */
+    private final class SoftRefReleaseThread extends Thread
+    {
+        private volatile boolean requestEnd; // used for inter-thread communication
+
+        private SoftRefReleaseThread()
+        {
+            setName(SoftRefReleaseThread.class.getName());
+            setDaemon(true);
+        }
+
+        public void run()
+        {
+            loop: while (!requestEnd && !Thread.currentThread().isInterrupted())
+            {
+                try
+                {
+                    Reference ref = refqueue.remove(TIMEOUT);
+                    if (ref == null)
+                    {
+                        continue;
+                    }
+
+                    FileSystemAndNameKey key;
+                    synchronized (refReverseMap)
+                    {
+                        key = (FileSystemAndNameKey) refReverseMap.get(ref);
+                    }
+
+                    if (key != null)
+                    {
+                        if (removeFile(key))
+                        {
+                            /* This is not thread safe
+                            filesystemClose(key.getFileSystem());
+                            */
+                        }
+                    }
+                }
+                catch (InterruptedException e)
+                {
+                    if (!requestEnd)
+                    {
+                        VfsLog.warn(getLogger(), log,
+                                    Messages.getString("vfs.impl/SoftRefReleaseThread-interrupt.info"));
+                    }
+                    break loop;
+                }
+            }
+        }
+    }
+
+    public SoftRefFilesCache()
+    {
+    }
+
+    private void startThread()
+    {
+        if (softRefReleaseThread != null)
+        {
+            throw new IllegalStateException(
+                    Messages.getString("vfs.impl/SoftRefReleaseThread-already-running.warn"));
+        }
+
+        softRefReleaseThread = new SoftRefReleaseThread();
+        softRefReleaseThread.start();
+    }
+
+    private void endThread()
+    {
+        if (softRefReleaseThread != null)
+        {
+            softRefReleaseThread.requestEnd = true;
+            softRefReleaseThread.interrupt();
+            softRefReleaseThread = null;
+        }
+    }
+
+    public void putFile(final FileObject file)
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("putFile: " + file.getName());
+        }
+
+        Map files = getOrCreateFilesystemCache(file.getFileSystem());
+
+        Reference ref = createReference(file, refqueue);
+        FileSystemAndNameKey key = new FileSystemAndNameKey(file
+                .getFileSystem(), file.getName());
+
+        synchronized (files)
+        {
+            Reference old = (Reference) files.put(file.getName(), ref);
+            synchronized (refReverseMap)
+            {
+                if (old != null)
+                {
+                    refReverseMap.remove(old);
+                }
+                refReverseMap.put(ref, key);
+            }
+        }
+    }
+
+    protected Reference createReference(FileObject file, ReferenceQueue refqueue)
+    {
+        return new SoftReference(file, refqueue);
+    }
+
+    public FileObject getFile(final FileSystem filesystem, final FileName name)
+    {
+        Map files = getOrCreateFilesystemCache(filesystem);
+
+        synchronized (files)
+        {
+            Reference ref = (Reference) files.get(name);
+            if (ref == null)
+            {
+                return null;
+            }
+
+            FileObject fo = (FileObject) ref.get();
+            if (fo == null)
+            {
+                removeFile(filesystem, name);
+            }
+            return fo;
+        }
+    }
+
+    public void clear(FileSystem filesystem)
+    {
+        Map files = getOrCreateFilesystemCache(filesystem);
+
+        boolean closeFilesystem;
+
+        synchronized (files)
+        {
+            synchronized (refReverseMap)
+            {
+                Iterator iterKeys = refReverseMap.values().iterator();
+                while (iterKeys.hasNext())
+                {
+                    FileSystemAndNameKey key = (FileSystemAndNameKey) iterKeys.next();
+                    if (key.getFileSystem() == filesystem)
+                    {
+                        iterKeys.remove();
+                        files.remove(key.getFileName());
+                    }
+                }
+
+                closeFilesystem = files.size() < 1;
+            }
+        }
+
+        if (closeFilesystem)
+        {
+            filesystemClose(filesystem);
+        }
+    }
+
+    private void filesystemClose(FileSystem filesystem)
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("close fs: " + filesystem.getRootName());
+        }
+        synchronized (filesystemCache)
+        {
+            filesystemCache.remove(filesystem);
+            if (filesystemCache.size() < 1)
+            {
+                endThread();
+            }
+        }
+        ((DefaultFileSystemManager) getContext().getFileSystemManager())
+                ._closeFileSystem(filesystem);
+    }
+
+    public void close()
+    {
+        super.close();
+
+        endThread();
+
+        // files.clear();
+        synchronized (filesystemCache)
+        {
+            filesystemCache.clear();
+        }
+
+        synchronized (refReverseMap)
+        {
+            refReverseMap.clear();
+        }
+    }
+
+    public void removeFile(FileSystem filesystem, FileName name)
+    {
+        if (removeFile(new FileSystemAndNameKey(filesystem, name)))
+        {
+            filesystemClose(filesystem);
+        }
+    }
+
+    public void touchFile(FileObject file)
+    {
+    }
+
+    private boolean removeFile(final FileSystemAndNameKey key)
+    {
+        if (log.isDebugEnabled())
+        {
+            log.debug("removeFile: " + key.getFileName());
+        }
+
+        Map files = getOrCreateFilesystemCache(key.getFileSystem());
+
+        synchronized (files)
+        {
+            Object ref = files.remove(key.getFileName());
+            if (ref != null)
+            {
+                synchronized (refReverseMap)
+                {
+                    refReverseMap.remove(ref);
+                }
+            }
+
+            return files.size() < 1;
+        }
+    }
+
+    protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
+    {
+        synchronized (filesystemCache)
+        {
+            if (filesystemCache.size() < 1)
+            {
+                startThread();
+            }
+
+            Map files = (Map) filesystemCache.get(filesystem);
+            if (files == null)
+            {
+                files = new HashMap();
+                filesystemCache.put(filesystem, files);
+            }
+
+            return files;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/WeakRefFilesCache.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/WeakRefFilesCache.java
new file mode 100644
index 0000000..49c21d2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/WeakRefFilesCache.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileObject;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * This implementation caches every file as long as it is strongly reachable by
+ * the java vm. As soon as the object is no longer reachable it will be discarded.
+ * In contrast to the SoftRefFilesCache this implementation might free resources faster
+ * as it don't wait until a memory limitation.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date: 2005-09-30 09:02:41 +0200 (Fr, 30 Sep
+ *          2005) $
+ * @see java.lang.ref.WeakReference
+ */
+public class WeakRefFilesCache extends SoftRefFilesCache
+{
+    protected Reference createReference(FileObject file, ReferenceQueue refqueue)
+    {
+        return new WeakReference(file, refqueue);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/package.html
new file mode 100644
index 0000000..55f796a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/cache/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>VFS File caching</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/AbstractFileChangeEvent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/AbstractFileChangeEvent.java
new file mode 100644
index 0000000..0d87611
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/AbstractFileChangeEvent.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.events;
+
+import org.apache.commons.vfs.FileChangeEvent;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * A change event that knows how to notify a listener.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public abstract class AbstractFileChangeEvent extends FileChangeEvent
+{
+    public AbstractFileChangeEvent(final FileObject file)
+    {
+        super(file);
+    }
+
+    public abstract void notify(final FileListener listener) throws Exception;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/ChangedEvent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/ChangedEvent.java
new file mode 100644
index 0000000..9c04967
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/ChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.events;
+
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * File changed event.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class ChangedEvent extends AbstractFileChangeEvent
+{
+    public ChangedEvent(final FileObject file)
+    {
+        super(file);
+    }
+
+    public void notify(final FileListener listener) throws Exception
+    {
+        listener.fileChanged(this);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/CreateEvent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/CreateEvent.java
new file mode 100644
index 0000000..bb5a890
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/CreateEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.events;
+
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * File creation event.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class CreateEvent extends AbstractFileChangeEvent
+{
+    public CreateEvent(final FileObject file)
+    {
+        super(file);
+    }
+
+    public void notify(final FileListener listener) throws Exception
+    {
+        listener.fileCreated(this);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/DeleteEvent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/DeleteEvent.java
new file mode 100644
index 0000000..950d8cc
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/DeleteEvent.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.events;
+
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * File deletion event.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class DeleteEvent extends AbstractFileChangeEvent
+{
+    public DeleteEvent(final FileObject file)
+    {
+        super(file);
+    }
+
+    public void notify(final FileListener listener) throws Exception
+    {
+        listener.fileDeleted(this);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/package.html
new file mode 100644
index 0000000..acbdf79
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/events/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>VFS Events</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DecoratedFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DecoratedFileObject.java
new file mode 100644
index 0000000..3c4c1bd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DecoratedFileObject.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import java.net.URL;
+import java.util.List;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.operations.FileOperations;
+
+/**
+ * Base class to build a fileObject decoration.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class DecoratedFileObject implements FileObject
+{
+    private final FileObject decoratedFileObject;
+
+    public DecoratedFileObject(FileObject decoratedFileObject)
+    {
+        super();
+        this.decoratedFileObject = decoratedFileObject;
+    }
+
+    public boolean canRenameTo(FileObject newfile)
+    {
+        return decoratedFileObject.canRenameTo(newfile);
+    }
+
+    public void close() throws FileSystemException
+    {
+        decoratedFileObject.close();
+    }
+
+    public void copyFrom(FileObject srcFile, FileSelector selector) throws FileSystemException
+    {
+        decoratedFileObject.copyFrom(srcFile, selector);
+    }
+
+    public void createFile() throws FileSystemException
+    {
+        decoratedFileObject.createFile();
+    }
+
+    public void createFolder() throws FileSystemException
+    {
+        decoratedFileObject.createFolder();
+    }
+
+    public boolean delete() throws FileSystemException
+    {
+        return decoratedFileObject.delete();
+    }
+
+    public int delete(FileSelector selector) throws FileSystemException
+    {
+        return decoratedFileObject.delete(selector);
+    }
+
+    public boolean exists() throws FileSystemException
+    {
+        return decoratedFileObject.exists();
+    }
+
+    public void findFiles(FileSelector selector, boolean depthwise, List selected) throws FileSystemException
+    {
+        decoratedFileObject.findFiles(selector, depthwise, selected);
+    }
+
+    public FileObject[] findFiles(FileSelector selector) throws FileSystemException
+    {
+        return decoratedFileObject.findFiles(selector);
+    }
+
+    public FileObject getChild(String name) throws FileSystemException
+    {
+        return decoratedFileObject.getChild(name);
+    }
+
+    public FileObject[] getChildren() throws FileSystemException
+    {
+        return decoratedFileObject.getChildren();
+    }
+
+    public FileContent getContent() throws FileSystemException
+    {
+        return decoratedFileObject.getContent();
+    }
+
+    public FileSystem getFileSystem()
+    {
+        return decoratedFileObject.getFileSystem();
+    }
+
+    public FileName getName()
+    {
+        return decoratedFileObject.getName();
+    }
+
+    public FileObject getParent() throws FileSystemException
+    {
+        return decoratedFileObject.getParent();
+    }
+
+    public FileType getType() throws FileSystemException
+    {
+        return decoratedFileObject.getType();
+    }
+
+    public URL getURL() throws FileSystemException
+    {
+        return decoratedFileObject.getURL();
+    }
+
+    public boolean isHidden() throws FileSystemException
+    {
+        return decoratedFileObject.isHidden();
+    }
+
+    public boolean isReadable() throws FileSystemException
+    {
+        return decoratedFileObject.isReadable();
+    }
+
+    public boolean isWriteable() throws FileSystemException
+    {
+        return decoratedFileObject.isWriteable();
+    }
+
+    public void moveTo(FileObject destFile) throws FileSystemException
+    {
+        decoratedFileObject.moveTo(destFile);
+    }
+
+    public FileObject resolveFile(String name, NameScope scope) throws FileSystemException
+    {
+        return decoratedFileObject.resolveFile(name, scope);
+    }
+
+    public FileObject resolveFile(String path) throws FileSystemException
+    {
+        return decoratedFileObject.resolveFile(path);
+    }
+
+    public void refresh() throws FileSystemException
+    {
+        decoratedFileObject.refresh();
+    }
+
+    public FileObject getDecoratedFileObject()
+    {
+        return decoratedFileObject;
+    }
+
+    public boolean isAttached()
+    {
+        return decoratedFileObject.isAttached();
+    }
+
+    public boolean isContentOpen()
+    {
+        return decoratedFileObject.isContentOpen();
+    }
+
+    public String toString()
+    {
+        return decoratedFileObject.toString();
+    }
+
+    public FileOperations getFileOperations() throws FileSystemException
+    {
+        return decoratedFileObject.getFileOperations();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileContentInfo.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileContentInfo.java
new file mode 100644
index 0000000..1ae9e09
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileContentInfo.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileContentInfo;
+
+/**
+ * The default file content information.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class DefaultFileContentInfo implements FileContentInfo
+{
+    private final String contentType;
+    private final String contentEncoding;
+
+    public DefaultFileContentInfo(final String contentType, final String contentEncoding)
+    {
+        this.contentType = contentType;
+        this.contentEncoding = contentEncoding;
+    }
+
+    public String getContentType()
+    {
+        return contentType;
+    }
+
+    public String getContentEncoding()
+    {
+        return contentEncoding;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java
new file mode 100644
index 0000000..e2accd8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java
@@ -0,0 +1,691 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileMonitor;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * A polling {@link FileMonitor} implementation.<br />
+ * <br />
+ * The DefaultFileMonitor is a Thread based polling file system monitor with a 1
+ * second delay.<br />
+ * <br />
+ * <b>Design:</b>
+ * <p>
+ * There is a Map of monitors known as FileMonitorAgents. With the thread running,
+ * each FileMonitorAgent object is asked to "check" on the file it is
+ * responsible for.
+ * To do this check, the cache is cleared.
+ * </p>
+ * <ul>
+ * <li>If the file existed before the refresh and it no longer exists, a delete
+ * event is fired.</li>
+ * <li>If the file existed before the refresh and it still exists, check the
+ * last modified timestamp to see if that has changed.</li>
+ * <li>If it has, fire a change event.</li>
+ * </ul>
+ * <p>
+ * With each file delete, the FileMonitorAgent of the parent is asked to
+ * re-build its
+ * list of children, so that they can be accurately checked when there are new
+ * children.<br/>
+ * New files are detected during each "check" as each file does a check for new
+ * children.
+ * If new children are found, create events are fired recursively if recursive
+ * descent is
+ * enabled.
+ * </p>
+ * <p>
+ * For performance reasons, added a delay that increases as the number of files
+ * monitored
+ * increases. The default is a delay of 1 second for every 1000 files processed.
+ * </p>
+ * <br /><b>Example usage:</b><br /><pre>
+ * FileSystemManager fsManager = VFS.getManager();
+ * FileObject listendir = fsManager.resolveFile("/home/username/monitored/");
+ * <p/>
+ * DefaultFileMonitor fm = new DefaultFileMonitor(new CustomFileListener());
+ * fm.setRecursive(true);
+ * fm.addFile(listendir);
+ * fm.start();
+ * </pre>
+ * <i>(where CustomFileListener is a class that implements the FileListener
+ * interface.)</i>
+ *
+ * @author <a href="mailto:xknight@users.sourceforge.net">Christopher Ottley</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultFileMonitor implements Runnable, FileMonitor
+{
+    private static final Log LOG = LogFactory.getLog(DefaultFileMonitor.class);
+
+    private static final long DEFAULT_DELAY = 1000;
+
+    private static final int DEFAULT_MAX_FILES = 1000;
+
+    /**
+     * Map from FileName to FileObject being monitored.
+     */
+    private final Map monitorMap = new HashMap();
+
+    /**
+     * The low priority thread used for checking the files being monitored.
+     */
+    private Thread monitorThread;
+
+    /**
+     * File objects to be removed from the monitor map.
+     */
+    private final Stack deleteStack = new Stack();
+
+    /**
+     * File objects to be added to the monitor map.
+     */
+    private final Stack addStack = new Stack();
+
+    /**
+     * A flag used to determine if the monitor thread should be running.
+     */
+    private volatile boolean shouldRun = true; // used for inter-thread communication
+
+    /**
+     * A flag used to determine if adding files to be monitored should be recursive.
+     */
+    private boolean recursive;
+
+    /**
+     * Set the delay between checks
+     */
+    private long delay = DEFAULT_DELAY;
+
+    /**
+     * Set the number of files to check until a delay will be inserted
+     */
+    private int checksPerRun = DEFAULT_MAX_FILES;
+
+    /**
+     * A listener object that if set, is notified on file creation and deletion.
+     */
+    private final FileListener listener;
+
+    public DefaultFileMonitor(final FileListener listener)
+    {
+        this.listener = listener;
+    }
+
+    /**
+     * Access method to get the recursive setting when adding files for monitoring.
+     * @return true if monitoring is enabled for children.
+     */
+    public boolean isRecursive()
+    {
+        return this.recursive;
+    }
+
+    /**
+     * Access method to set the recursive setting when adding files for monitoring.
+     * @param newRecursive true if monitoring should be enabled for children.
+     */
+    public void setRecursive(final boolean newRecursive)
+    {
+        this.recursive = newRecursive;
+    }
+
+    /**
+     * Access method to get the current FileListener object notified when there
+     * are changes with the files added.
+     * @return The FileListener.
+     */
+    FileListener getFileListener()
+    {
+        return this.listener;
+    }
+
+    /**
+     * Adds a file to be monitored.
+     * @param file The FileObject to monitor.
+     */
+    public void addFile(final FileObject file)
+    {
+        doAddFile(file);
+        try
+        {
+            // add all direct children too
+            if (file.getType().hasChildren())
+            {
+                // Traverse the children
+                final FileObject[] children = file.getChildren();
+                for (int i = 0; i < children.length; i++)
+                {
+                    doAddFile(children[i]);
+                }
+            }
+        }
+        catch (FileSystemException fse)
+        {
+            LOG.error(fse.getLocalizedMessage(), fse);
+        }
+    }
+
+    /**
+     * Adds a file to be monitored.
+     * @param file The FileObject to add.
+     */
+    private void doAddFile(final FileObject file)
+    {
+        synchronized (this.monitorMap)
+        {
+            if (this.monitorMap.get(file.getName()) == null)
+            {
+                this.monitorMap.put(file.getName(), new FileMonitorAgent(this,
+                    file));
+
+                try
+                {
+                    if (this.listener != null)
+                    {
+                        file.getFileSystem().addListener(file, this.listener);
+                    }
+
+                    if (file.getType().hasChildren() && this.recursive)
+                    {
+                        // Traverse the children
+                        final FileObject[] children = file.getChildren();
+                        for (int i = 0; i < children.length; i++)
+                        {
+                            this.addFile(children[i]); // Add depth first
+                        }
+                    }
+
+                }
+                catch (FileSystemException fse)
+                {
+                    LOG.error(fse.getLocalizedMessage(), fse);
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Removes a file from being monitored.
+     * @param file The FileObject to remove from monitoring.
+     */
+    public void removeFile(final FileObject file)
+    {
+        synchronized (this.monitorMap)
+        {
+            FileName fn = file.getName();
+            if (this.monitorMap.get(fn) != null)
+            {
+                FileObject parent;
+                try
+                {
+                    parent = file.getParent();
+                }
+                catch (FileSystemException fse)
+                {
+                    parent = null;
+                }
+
+                this.monitorMap.remove(fn);
+
+                if (parent != null)
+                { // Not the root
+                    FileMonitorAgent parentAgent =
+                        (FileMonitorAgent) this.monitorMap.get(parent.getName());
+                    if (parentAgent != null)
+                    {
+                        parentAgent.resetChildrenList();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Queues a file for removal from being monitored.
+     * @param file The FileObject to be removed from being monitored.
+     */
+    protected void queueRemoveFile(final FileObject file)
+    {
+        this.deleteStack.push(file);
+    }
+
+    /**
+     * Get the delay between runs.
+     * @return The delay period.
+     */
+    public long getDelay()
+    {
+        return delay;
+    }
+
+    /**
+     * Set the delay between runs.
+     * @param delay The delay period.
+     */
+    public void setDelay(long delay)
+    {
+        if (delay > 0)
+        {
+            this.delay = delay;
+        }
+        else
+        {
+            this.delay = DEFAULT_DELAY;
+        }
+    }
+
+    /**
+     * get the number of files to check per run.
+     * @return The number of files to check per iteration.
+     */
+    public int getChecksPerRun()
+    {
+        return checksPerRun;
+    }
+
+    /**
+     * set the number of files to check per run.
+     * a additional delay will be added if there are more files to check
+     *
+     * @param checksPerRun a value less than 1 will disable this feature
+     */
+    public void setChecksPerRun(int checksPerRun)
+    {
+        this.checksPerRun = checksPerRun;
+    }
+
+    /**
+     * Queues a file for addition to be monitored.
+     * @param file The FileObject to add.
+     */
+    protected void queueAddFile(final FileObject file)
+    {
+        this.addStack.push(file);
+    }
+
+    /**
+     * Starts monitoring the files that have been added.
+     */
+    public void start()
+    {
+        if (this.monitorThread == null)
+        {
+            this.monitorThread = new Thread(this);
+            this.monitorThread.setDaemon(true);
+            this.monitorThread.setPriority(Thread.MIN_PRIORITY);
+        }
+        this.monitorThread.start();
+    }
+
+    /**
+     * Stops monitoring the files that have been added.
+     */
+    public void stop()
+    {
+        this.shouldRun = false;
+    }
+
+    /**
+     * Asks the agent for each file being monitored to check its file for changes.
+     */
+    public void run()
+    {
+        mainloop:
+        while (!monitorThread.isInterrupted() && this.shouldRun)
+        {
+            while (!this.deleteStack.empty())
+            {
+                this.removeFile((FileObject) this.deleteStack.pop());
+            }
+
+            // For each entry in the map
+            Object[] fileNames;
+            synchronized (this.monitorMap)
+            {
+                fileNames = this.monitorMap.keySet().toArray();
+            }
+            for (int iterFileNames = 0; iterFileNames < fileNames.length;
+                 iterFileNames++)
+            {
+                FileName fileName = (FileName) fileNames[iterFileNames];
+                FileMonitorAgent agent;
+                synchronized (this.monitorMap)
+                {
+                    agent = (FileMonitorAgent) this.monitorMap.get(fileName);
+                }
+                if (agent != null)
+                {
+                    agent.check();
+                }
+
+                if (getChecksPerRun() > 0)
+                {
+                    if ((iterFileNames % getChecksPerRun()) == 0)
+                    {
+                        try
+                        {
+                            Thread.sleep(getDelay());
+                        }
+                        catch (InterruptedException e)
+                        {
+                            // Woke up.
+                        }
+                    }
+                }
+
+                if (monitorThread.isInterrupted() || !this.shouldRun)
+                {
+                    continue mainloop;
+                }
+            }
+
+            while (!this.addStack.empty())
+            {
+                this.addFile((FileObject) this.addStack.pop());
+            }
+
+            try
+            {
+                Thread.sleep(getDelay());
+            }
+            catch (InterruptedException e)
+            {
+                continue;
+            }
+        }
+
+        this.shouldRun = true;
+    }
+
+    /**
+     * File monitor agent.
+     */
+    private static final class FileMonitorAgent
+    {
+        private final FileObject file;
+        private final DefaultFileMonitor fm;
+
+        private boolean exists;
+        private long timestamp;
+        private Map children;
+
+        private FileMonitorAgent(DefaultFileMonitor fm, FileObject file)
+        {
+            this.fm = fm;
+            this.file = file;
+
+            this.refresh();
+            this.resetChildrenList();
+
+            try
+            {
+                this.exists = this.file.exists();
+            }
+            catch (FileSystemException fse)
+            {
+                this.exists = false;
+                this.timestamp = -1;
+            }
+
+            if (this.exists)
+            {
+                try
+                {
+                    this.timestamp = this.file.getContent().getLastModifiedTime();
+                }
+                catch (FileSystemException fse)
+                {
+                    this.timestamp = -1;
+                }
+            }
+        }
+
+        private void resetChildrenList()
+        {
+            try
+            {
+                if (this.file.getType().hasChildren())
+                {
+                    this.children = new HashMap();
+                    FileObject[] childrenList = this.file.getChildren();
+                    for (int i = 0; i < childrenList.length; i++)
+                    {
+                        this.children.put(childrenList[i].getName(), new
+                            Object()); // null?
+                    }
+                }
+            }
+            catch (FileSystemException fse)
+            {
+                this.children = null;
+            }
+        }
+
+
+        /**
+         * Clear the cache and re-request the file object
+         */
+        private void refresh()
+        {
+            try
+            {
+                this.file.refresh();
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+
+        /**
+         * Recursively fires create events for all children if recursive descent is
+         * enabled. Otherwise the create event is only fired for the initial
+         * FileObject.
+         * @param child The child to add.
+         */
+        private void fireAllCreate(FileObject child)
+        {
+            // Add listener so that it can be triggered
+            if (this.fm.getFileListener() != null)
+            {
+                child.getFileSystem().addListener(child, this.fm.getFileListener());
+            }
+
+            ((AbstractFileSystem) child.getFileSystem()).fireFileCreated(child);
+
+            // Remove it because a listener is added in the queueAddFile
+            if (this.fm.getFileListener() != null)
+            {
+                child.getFileSystem().removeListener(child,
+                    this.fm.getFileListener());
+            }
+
+            this.fm.queueAddFile(child); // Add
+
+            try
+            {
+
+                if (this.fm.isRecursive())
+                {
+                    if (child.getType().hasChildren())
+                    {
+                        FileObject[] newChildren = child.getChildren();
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            fireAllCreate(newChildren[i]);
+                        }
+                    }
+                }
+
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+        /**
+         * Only checks for new children. If children are removed, they'll
+         * eventually be checked.
+         */
+        private void checkForNewChildren()
+        {
+            try
+            {
+                if (this.file.getType().hasChildren())
+                {
+                    FileObject[] newChildren = this.file.getChildren();
+                    if (this.children != null)
+                    {
+                        // See which new children are not listed in the current children map.
+                        Map newChildrenMap = new HashMap();
+                        Stack missingChildren = new Stack();
+
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            newChildrenMap.put(newChildren[i].getName(), new
+                                Object()); // null ?
+                            // If the child's not there
+                            if
+                                (!this.children.containsKey(newChildren[i].getName()))
+                            {
+                                missingChildren.push(newChildren[i]);
+                            }
+                        }
+
+                        this.children = newChildrenMap;
+
+                        // If there were missing children
+                        if (!missingChildren.empty())
+                        {
+
+                            while (!missingChildren.empty())
+                            {
+                                FileObject child = (FileObject)
+                                    missingChildren.pop();
+                                this.fireAllCreate(child);
+                            }
+                        }
+
+                    }
+                    else
+                    {
+                        // First set of children - Break out the cigars
+                        if (newChildren.length > 0)
+                        {
+                            this.children = new HashMap();
+                        }
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            this.children.put(newChildren[i].getName(), new
+                                Object()); // null?
+                            this.fireAllCreate(newChildren[i]);
+                        }
+                    }
+                }
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+        private void check()
+        {
+            this.refresh();
+
+            try
+            {
+                // If the file existed and now doesn't
+                if (this.exists && !this.file.exists())
+                {
+                    this.exists = this.file.exists();
+                    this.timestamp = -1;
+
+                    // Fire delete event
+
+                    ((AbstractFileSystem)
+                        this.file.getFileSystem()).fireFileDeleted(this.file);
+
+                    // Remove listener in case file is re-created. Don't want to fire twice.
+                    if (this.fm.getFileListener() != null)
+                    {
+                        this.file.getFileSystem().removeListener(this.file,
+                            this.fm.getFileListener());
+                    }
+
+                    // Remove from map
+                    this.fm.queueRemoveFile(this.file);
+                }
+                else if (this.exists && this.file.exists())
+                {
+
+                    // Check the timestamp to see if it has been modified
+                    if (this.timestamp != this.file.getContent().getLastModifiedTime())
+                    {
+                        this.timestamp = this.file.getContent().getLastModifiedTime();
+                        // Fire change event
+
+                        // Don't fire if it's a folder because new file children
+                        // and deleted files in a folder have their own event triggered.
+                        if (!this.file.getType().hasChildren())
+                        {
+                            ((AbstractFileSystem)
+                                this.file.getFileSystem()).fireFileChanged(this.file);
+                        }
+                    }
+
+                }
+                else if (!this.exists && this.file.exists())
+                {
+                    this.exists = this.file.exists();
+                    this.timestamp = this.file.getContent().getLastModifiedTime();
+                    // Don't fire if it's a folder because new file children
+                    // and deleted files in a folder have their own event triggered.
+                    if (!this.file.getType().hasChildren())
+                    {
+                        ((AbstractFileSystem)
+                                this.file.getFileSystem()).fireFileCreated(this.file);
+                    }
+                }
+
+                this.checkForNewChildren();
+
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java
new file mode 100644
index 0000000..eb8555a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.provider.AbstractVfsComponent;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.Messages;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * A simple file replicator and temporary file store.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultFileReplicator
+    extends AbstractVfsComponent
+    implements FileReplicator, TemporaryFileStore
+{
+    private static final char[] TMP_RESERVED_CHARS = new char[]
+        {
+            '?', '/', '\\', ' ', '&', '"', '\'', '*', '#', ';', ':', '<', '>', '|'
+        };
+    private static final Log log = LogFactory.getLog(DefaultFileReplicator.class);
+
+    private static final int MASK = 0xffff;
+
+    private final ArrayList copies = new ArrayList();
+    private File tempDir;
+    private long filecount;
+    private boolean tempDirMessageLogged;
+
+    /**
+     * constructor to set the location of the temporary directory.
+     *
+     * @param tempDir The temporary directory.
+     */
+    public DefaultFileReplicator(final File tempDir)
+    {
+        this.tempDir = tempDir;
+    }
+
+    public DefaultFileReplicator()
+    {
+    }
+
+    /**
+     * Initialises this component.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+        if (tempDir == null)
+        {
+            String baseTmpDir = System.getProperty("java.io.tmpdir");
+
+            tempDir = new File(baseTmpDir, "vfs_cache").getAbsoluteFile();
+        }
+
+        filecount = new Random().nextInt() & MASK;
+
+        if (!tempDirMessageLogged)
+        {
+            final String message = Messages.getString("vfs.impl/temp-dir.info", tempDir);
+            VfsLog.info(getLogger(), log, message);
+
+            tempDirMessageLogged = true;
+        }
+    }
+
+    /**
+     * Closes the replicator, deleting all temporary files.
+     */
+    public void close()
+    {
+        // Delete the temporary files
+        synchronized (copies)
+        {
+            while (copies.size() > 0)
+            {
+                final File file = (File) removeFile();
+                deleteFile(file);
+            }
+        }
+
+        // Clean up the temp directory, if it is empty
+        if (tempDir != null && tempDir.exists() && tempDir.list().length == 0)
+        {
+            tempDir.delete();
+            tempDir = null;
+        }
+    }
+
+    /**
+     * physically deletes the file from the filesystem
+     * @param file The File to delete.
+     */
+    protected void deleteFile(File file)
+    {
+        try
+        {
+            final FileObject fileObject = getContext().toFileObject(file);
+            fileObject.delete(Selectors.SELECT_ALL);
+        }
+        catch (final FileSystemException e)
+        {
+            final String message = Messages.getString("vfs.impl/delete-temp.warn", file.getName());
+            VfsLog.warn(getLogger(), log, message, e);
+        }
+    }
+
+    /**
+     * removes a file from the copies list. Will be used for cleanup. <br/>
+     * Notice: The system awaits that the returning object can be cast to a java.io.File
+     * @return the File that was removed.
+     */
+    protected Object removeFile()
+    {
+        synchronized (copies)
+        {
+            return copies.remove(0);
+        }
+    }
+
+    /**
+     * removes a instance from the list of copies
+     * @param file The File to remove.
+     */
+    protected void removeFile(Object file)
+    {
+        synchronized (copies)
+        {
+            copies.remove(file);
+        }
+    }
+
+    /**
+     * Allocates a new temporary file.
+     * @param baseName the base file name.
+     * @return The created File.
+     * @throws FileSystemException if an error occurs.
+     */
+    public File allocateFile(final String baseName) throws FileSystemException
+    {
+        // Create a unique-ish file name
+        final String basename = createFilename(baseName);
+        synchronized (this)
+        {
+            filecount++;
+        }
+
+        return createAndAddFile(tempDir, basename);
+    }
+
+    protected File createAndAddFile(final File parent, final String basename) throws FileSystemException
+    {
+        final File file = createFile(tempDir, basename);
+
+        // Keep track to delete later
+        addFile(file);
+
+        return file;
+    }
+
+    protected void addFile(Object file)
+    {
+        synchronized (copies)
+        {
+            copies.add(file);
+        }
+    }
+
+    protected long getFilecount()
+    {
+        return filecount;
+    }
+
+    /**
+     * create the temporary file name
+     * @param baseName The base to prepend to the file name being created.
+     * @return the name of the File.
+     */
+    protected String createFilename(final String baseName)
+    {
+        // BUG29007
+        // return baseName + "_" + getFilecount() + ".tmp";
+
+        // imario@apache.org: BUG34976 get rid of maybe reserved and dangerous characters
+        // e.g. to allow replication of http://hostname.org/fileservlet?file=abc.txt
+        String safeBasename = UriParser.encode(baseName, TMP_RESERVED_CHARS).replace('%', '_');
+        return "tmp_" + getFilecount() + "_" + safeBasename;
+    }
+
+    /**
+     * create the temporary file
+     * @param parent The file to use as the parent of the file being created.
+     * @param name The name of the file to create.
+     * @return The File that was created.
+     * @throws FileSystemException if an error occurs creating the file.
+     */
+    protected File createFile(final File parent, final String name) throws FileSystemException
+    {
+        return new File(parent, UriParser.decode(name));
+    }
+
+    /**
+     * Creates a local copy of the file, and all its descendents.
+     * @param srcFile The file to copy.
+     * @param selector The FileSelector.
+     * @return the created File.
+     * @throws FileSystemException if an error occurs copying the file.
+     */
+    public File replicateFile(final FileObject srcFile,
+                              final FileSelector selector)
+        throws FileSystemException
+    {
+        final String basename = srcFile.getName().getBaseName();
+        final File file = allocateFile(basename);
+
+        // Copy from the source file
+        final FileObject destFile = getContext().toFileObject(file);
+        destFile.copyFrom(srcFile, selector);
+
+        return file;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java
new file mode 100644
index 0000000..918521b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticator;
+
+/**
+ * Default options usable for all filesystems.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class DefaultFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    /** The default FileSystemConfigBuilder */
+    private static final DefaultFileSystemConfigBuilder BUILDER = new DefaultFileSystemConfigBuilder();
+
+    public static DefaultFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * Sets the user authenticator to get authentication informations.
+     * @param opts The FileSystemOptions.
+     * @param userAuthenticator The UserAuthenticator.
+     * @throws FileSystemException if an error occurs setting the UserAuthenticator.
+     */
+    public void setUserAuthenticator(FileSystemOptions opts, UserAuthenticator userAuthenticator)
+            throws FileSystemException
+    {
+        setParam(opts, "userAuthenticator", userAuthenticator);
+    }
+
+    /**
+     * @see #setUserAuthenticator
+     * @param opts The FileSystemOptions.
+     * @return The UserAuthenticator.
+     */
+    public UserAuthenticator getUserAuthenticator(FileSystemOptions opts)
+    {
+        return (UserAuthenticator) getParam(opts, "userAuthenticator");
+    }
+
+    protected Class getConfigClass()
+    {
+        return DefaultFileSystemConfigBuilder.class;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java
new file mode 100644
index 0000000..2b4d26a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java
@@ -0,0 +1,1170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.CacheStrategy;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.VFS;
+import org.apache.commons.vfs.cache.SoftRefFilesCache;
+import org.apache.commons.vfs.operations.FileOperationProvider;
+import org.apache.commons.vfs.provider.AbstractFileName;
+import org.apache.commons.vfs.provider.AbstractFileProvider;
+import org.apache.commons.vfs.provider.DefaultURLStreamHandler;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.LocalFileProvider;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.VfsComponent;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A default file system manager implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date: 2006-03-30 21:16:24 +0200 (Do, 30 Mrz
+ *          2006) $
+ */
+public class DefaultFileSystemManager implements FileSystemManager
+{
+    /**
+     * The provider for local files.
+     */
+    private LocalFileProvider localFileProvider;
+
+    /**
+     * The default provider.
+     */
+    private FileProvider defaultProvider;
+
+    /**
+     * The file replicator to use.
+     */
+    private FileReplicator fileReplicator;
+
+    /**
+     * Mapping from URI scheme to FileProvider.
+     */
+    private final Map providers = new HashMap();
+
+    /**
+     * All components used by this manager.
+     */
+    private final ArrayList components = new ArrayList();
+
+    /**
+     * The base file to use for relative URI.
+     */
+    private FileObject baseFile;
+
+    /**
+     * The files cache
+     */
+    private FilesCache filesCache;
+
+    /**
+     * The cache strategy
+     */
+    private CacheStrategy fileCacheStrategy;
+
+    /**
+     * Class which decorates all returned fileObjects
+     */
+    private Class fileObjectDecorator;
+    private Constructor fileObjectDecoratorConst;
+
+    /**
+     * The class to use to determine the content-type (mime-type)
+     */
+    private FileContentInfoFactory fileContentInfoFactory;
+
+    /**
+     * The logger to use.
+     */
+    private Log log = LogFactory.getLog(getClass());
+
+    /**
+     * The context to pass to providers.
+     */
+    private final DefaultVfsComponentContext context = new DefaultVfsComponentContext(
+            this);
+
+    private TemporaryFileStore tempFileStore;
+    private final FileTypeMap map = new FileTypeMap();
+    private final VirtualFileProvider vfsProvider = new VirtualFileProvider();
+    private boolean init;
+
+    private final Map operationProviders = new HashMap();
+
+    /**
+     * Returns the logger used by this manager.
+     * @return the Logger.
+     */
+    protected Log getLogger()
+    {
+        return log;
+    }
+
+    /**
+     * Registers a file system provider. The manager takes care of all lifecycle
+     * management. A provider may be registered multiple times.
+     *
+     * @param urlScheme
+     *            The scheme the provider will handle.
+     * @param provider
+     *            The provider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addProvider(final String urlScheme, final FileProvider provider)
+            throws FileSystemException
+    {
+        addProvider(new String[] {urlScheme}, provider);
+    }
+
+    /**
+     * Registers a file system provider. The manager takes care of all lifecycle
+     * management. A provider may be registered multiple times.
+     *
+     * @param urlSchemes
+     *            The schemes the provider will handle.
+     * @param provider
+     *            The provider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addProvider(final String[] urlSchemes,
+            final FileProvider provider) throws FileSystemException
+    {
+        // Warn about duplicate providers
+        for (int i = 0; i < urlSchemes.length; i++)
+        {
+            final String scheme = urlSchemes[i];
+            if (providers.containsKey(scheme))
+            {
+                throw new FileSystemException(
+                        "vfs.impl/multiple-providers-for-scheme.error", scheme);
+            }
+        }
+
+        // Contextualise the component (if not already)
+        setupComponent(provider);
+
+        // Add to map
+        for (int i = 0; i < urlSchemes.length; i++)
+        {
+            final String scheme = urlSchemes[i];
+            providers.put(scheme, provider);
+        }
+
+        if (provider instanceof LocalFileProvider && localFileProvider == null)
+        {
+            localFileProvider = (LocalFileProvider) provider;
+        }
+    }
+
+    /**
+     * Returns true if this manager has a provider for a particular scheme.
+     * @param scheme The scheme to check.
+     * @return true if a provider is configured for this scheme, false otherwise.
+     */
+    public boolean hasProvider(final String scheme)
+    {
+        return providers.containsKey(scheme);
+    }
+
+    /**
+     * Adds an filename extension mapping.
+     *
+     * @param extension The file name extension.
+     * @param scheme The scheme to use for files with this extension.
+     */
+    public void addExtensionMap(final String extension, final String scheme)
+    {
+        map.addExtension(extension, scheme);
+    }
+
+    /**
+     * Adds a mime type mapping.
+     *
+     * @param mimeType The mime type.
+     * @param scheme The scheme to use for files with this mime type.
+     */
+    public void addMimeTypeMap(final String mimeType, final String scheme)
+    {
+        map.addMimeType(mimeType, scheme);
+    }
+
+    /**
+     * Sets the default provider. This is the provider that will handle URI with
+     * unknown schemes. The manager takes care of all lifecycle management.
+     * @param provider The FileProvider.
+     * @throws FileSystemException if an error occurs setting the provider.
+     */
+    public void setDefaultProvider(final FileProvider provider)
+            throws FileSystemException
+    {
+        setupComponent(provider);
+        defaultProvider = provider;
+    }
+
+    /**
+     * Returns the filesCache implementation used to cache files.
+     * @return The FilesCache.
+     */
+    public FilesCache getFilesCache()
+    {
+        return filesCache;
+    }
+
+    /**
+     * Sets the filesCache implementation used to cache files.
+     * @param filesCache The FilesCache.
+     * @throws FileSystemException if an error occurs setting the cache..
+     */
+    public void setFilesCache(final FilesCache filesCache)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.filesCache = filesCache;
+    }
+
+    /**
+     * <p>
+     * Set the cache strategy to use when dealing with file object data. You can
+     * set it only once before the FileSystemManager is initialized.
+     * <p />
+     * <p>
+     * The default is {@link CacheStrategy#ON_RESOLVE}
+     * </p>
+     *
+     * @param fileCacheStrategy The CacheStrategy to use.
+     * @throws FileSystemException
+     *             if this is not possible. e.g. it is already set.
+     */
+    public void setCacheStrategy(final CacheStrategy fileCacheStrategy)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.fileCacheStrategy = fileCacheStrategy;
+    }
+
+    /**
+     * Get the cache strategy used.
+     * @return The CacheStrategy.
+     */
+    public CacheStrategy getCacheStrategy()
+    {
+        return fileCacheStrategy;
+    }
+
+    /**
+     * Get the file object decorator used.
+     * @return The decorator.
+     */
+    public Class getFileObjectDecorator()
+    {
+        return fileObjectDecorator;
+    }
+
+    /**
+     * The constructor associated to the fileObjectDecorator.
+     * We cache it here for performance reasons.
+     * @return The decorator's Constructor.
+     */
+    public Constructor getFileObjectDecoratorConst()
+    {
+        return fileObjectDecoratorConst;
+    }
+
+    /**
+     * Set a fileObject decorator to be used for ALL returned file objects.
+     *
+     * @param fileObjectDecorator must be inherted from {@link DecoratedFileObject} a has to provide a
+     * constructor with a single {@link FileObject} as argument
+     * @throws FileSystemException if an error occurs setting the decorator.
+     */
+    public void setFileObjectDecorator(Class fileObjectDecorator) throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+        if (!DecoratedFileObject.class.isAssignableFrom(fileObjectDecorator))
+        {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName());
+        }
+
+        try
+        {
+            fileObjectDecoratorConst = fileObjectDecorator.getConstructor(new Class[]{FileObject.class});
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName(), e);
+        }
+
+        this.fileObjectDecorator = fileObjectDecorator;
+    }
+
+    /**
+     * get the fileContentInfoFactory used to determine the infos of a file
+     * content.
+     * @return The FileContentInfoFactory.
+     */
+    public FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return fileContentInfoFactory;
+    }
+
+    /**
+     * set the fileContentInfoFactory used to determine the infos of a file
+     * content.
+     * @param fileContentInfoFactory The FileContentInfoFactory.
+     * @throws FileSystemException if an error occurs setting the FileContentInfoFactory.
+     */
+    public void setFileContentInfoFactory(FileContentInfoFactory fileContentInfoFactory)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.fileContentInfoFactory = fileContentInfoFactory;
+    }
+
+    /**
+     * Sets the file replicator to use. The manager takes care of all lifecycle
+     * management.
+     * @param replicator The FileReplicator.
+     * @throws FileSystemException if an error occurs setting the replicator.
+     */
+    public void setReplicator(final FileReplicator replicator)
+            throws FileSystemException
+    {
+        setupComponent(replicator);
+        fileReplicator = replicator;
+    }
+
+    /**
+     * Sets the temporary file store to use. The manager takes care of all
+     * lifecycle management.
+     * @param tempFileStore The temporary FileStore.
+     * @throws FileSystemException if an error occurs adding the file store.
+     */
+    public void setTemporaryFileStore(final TemporaryFileStore tempFileStore)
+            throws FileSystemException
+    {
+        setupComponent(tempFileStore);
+        this.tempFileStore = tempFileStore;
+    }
+
+    /**
+     * Sets the logger to use.
+     * @param log The Logger to use.
+     */
+    public void setLogger(final Log log)
+    {
+        this.log = log;
+    }
+
+    /**
+     * Initialises a component, if it has not already been initialised.
+     * @param component The component to setup.
+     * @throws FileSystemException if an error occurs.
+     */
+    private void setupComponent(final Object component)
+            throws FileSystemException
+    {
+        if (!components.contains(component))
+        {
+            if (component instanceof VfsComponent)
+            {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.setLogger(getLogger());
+                vfsComponent.setContext(context);
+                vfsComponent.init();
+            }
+            components.add(component);
+        }
+    }
+
+    /**
+     * Closes a component, if it has not already been closed.
+     * @param component The component to close.
+     */
+    private void closeComponent(final Object component)
+    {
+        if (component != null && components.contains(component))
+        {
+            if (component instanceof VfsComponent)
+            {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.close();
+            }
+            components.remove(component);
+        }
+    }
+
+    /**
+     * Returns the file replicator.
+     *
+     * @return The file replicator. Never returns null.
+     * @throws FileSystemException if there is no FileReplicator.
+     */
+    public FileReplicator getReplicator() throws FileSystemException
+    {
+        if (fileReplicator == null)
+        {
+            throw new FileSystemException("vfs.impl/no-replicator.error");
+        }
+        return fileReplicator;
+    }
+
+    /**
+     * Returns the temporary file store.
+     *
+     * @return The file store. Never returns null.
+     * @throws FileSystemException if there is no TemporaryFileStore.
+     */
+    public TemporaryFileStore getTemporaryFileStore()
+            throws FileSystemException
+    {
+        if (tempFileStore == null)
+        {
+            throw new FileSystemException("vfs.impl/no-temp-file-store.error");
+        }
+        return tempFileStore;
+    }
+
+    /**
+     * Initialises this manager.
+     * @throws FileSystemException if an error occurs during initialization.
+     */
+    public void init() throws FileSystemException
+    {
+        if (filesCache == null)
+        {
+            // filesCache = new DefaultFilesCache();
+            filesCache = new SoftRefFilesCache();
+        }
+        if (fileContentInfoFactory == null)
+        {
+            fileContentInfoFactory = new FileContentInfoFilenameFactory();
+        }
+
+        if (fileCacheStrategy == null)
+        {
+            fileCacheStrategy = CacheStrategy.ON_RESOLVE;
+        }
+
+        setupComponent(filesCache);
+        setupComponent(vfsProvider);
+
+        init = true;
+    }
+
+    /**
+     * Closes all files created by this manager, and cleans up any temporary
+     * files. Also closes all providers and the replicator.
+     */
+    public void close()
+    {
+        if (!init)
+        {
+            return;
+        }
+
+        // Close the providers.
+        for (Iterator iterator = providers.values().iterator(); iterator
+                .hasNext();)
+        {
+            final Object provider = iterator.next();
+            closeComponent(provider);
+        }
+
+        // Close the other components
+        closeComponent(defaultProvider);
+        closeComponent(fileReplicator);
+        closeComponent(tempFileStore);
+
+        components.clear();
+        providers.clear();
+        filesCache.close();
+        localFileProvider = null;
+        defaultProvider = null;
+        fileReplicator = null;
+        tempFileStore = null;
+        init = false;
+    }
+
+    /**
+     * Free all resources used by unused filesystems created by this manager.
+     */
+    public void freeUnusedResources()
+    {
+        if (!init)
+        {
+            return;
+        }
+
+        // Close the providers.
+        for (Iterator iterator = providers.values().iterator(); iterator
+                .hasNext();)
+        {
+            final AbstractFileProvider provider = (AbstractFileProvider) iterator
+                    .next();
+            provider.freeUnusedResources();
+        }
+    }
+
+    /**
+     * Sets the base file to use when resolving relative URI.
+     * @param baseFile The new base FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setBaseFile(final FileObject baseFile)
+            throws FileSystemException
+    {
+        this.baseFile = baseFile;
+    }
+
+    /**
+     * Sets the base file to use when resolving relative URI.
+     * @param baseFile The new base FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setBaseFile(final File baseFile) throws FileSystemException
+    {
+        this.baseFile = getLocalFileProvider().findLocalFile(baseFile);
+    }
+
+    /**
+     * Returns the base file used to resolve relative URI.
+     * @return The FileObject that represents the base file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getBaseFile() throws FileSystemException
+    {
+        return baseFile;
+    }
+
+    /**
+     * Locates a file by URI.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final String uri) throws FileSystemException
+    {
+        // return resolveFile(baseFile, uri);
+        return resolveFile(getBaseFile(), uri);
+    }
+
+    /**
+     * Locate a file by URI, use the FileSystemOptions for file-system creation.
+     * @param uri The URI of the file to locate.
+     * @param fileSystemOptions The options for the FileSystem.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+
+    public FileObject resolveFile(final String uri,
+            final FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        // return resolveFile(baseFile, uri, fileSystemOptions);
+        return resolveFile(getBaseFile(), uri, fileSystemOptions);
+    }
+
+    /**
+     * Locates a file by URI.
+     * @param baseFile The base File to use to locate the file.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final File baseFile, final String uri)
+            throws FileSystemException
+    {
+        final FileObject baseFileObj = getLocalFileProvider().findLocalFile(
+                baseFile);
+        return resolveFile(baseFileObj, uri);
+    }
+
+    /**
+     * Resolves a URI, relative to a base file.
+     * @param baseFile The base FileOjbect to use to locate the file.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String uri)
+            throws FileSystemException
+    {
+        return resolveFile(baseFile, uri, baseFile == null ? null : baseFile
+                .getFileSystem().getFileSystemOptions());
+    }
+
+    /**
+     * Resolves a URI, realtive to a base file with specified FileSystem
+     * configuration.
+     * @param baseFile The base file.
+     * @param uri The file name. May be a fully qualified or relative path or a url.
+     * @param fileSystemOptions Options to pass to the file system.
+     * @return A FileObject representing the target file.
+     * @throws FileSystemException if an error occurs accessing the file.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String uri,
+            final FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        final FileObject realBaseFile;
+        if (baseFile != null && VFS.isUriStyle()
+                && baseFile.getName().getType() == FileType.FILE)
+        {
+            realBaseFile = baseFile.getParent();
+        }
+        else
+        {
+            realBaseFile = baseFile;
+        }
+        // TODO: use resolveName and use this name to resolve the fileObject
+
+        UriParser.checkUriEncoding(uri);
+
+        if (uri == null)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        // Extract the scheme
+        final String scheme = UriParser.extractScheme(uri);
+        if (scheme != null)
+        {
+            // An absolute URI - locate the provider
+            final FileProvider provider = (FileProvider) providers.get(scheme);
+            if (provider != null)
+            {
+                return provider.findFile(realBaseFile, uri, fileSystemOptions);
+            }
+            // Otherwise, assume a local file
+        }
+
+        // Handle absolute file names
+        if (localFileProvider != null
+                && localFileProvider.isAbsoluteLocalName(uri))
+        {
+            return localFileProvider.findLocalFile(uri);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider
+            if (defaultProvider == null)
+            {
+                throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                        new Object[] {scheme, uri});
+            }
+            return defaultProvider.findFile(realBaseFile, uri, fileSystemOptions);
+        }
+
+        // Assume a relative name - use the supplied base file
+        if (realBaseFile == null)
+        {
+            throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
+        }
+
+        return realBaseFile.resolveFile(uri);
+    }
+
+    /**
+     * Resolves a name, relative to the file. If the supplied name is an
+     * absolute path, then it is resolved relative to the root of the file
+     * system that the file belongs to. If a relative name is supplied, then it
+     * is resolved relative to this file name.
+     * @param root The base FileName.
+     * @param path The path to the file relative to the base FileName or an absolute path.
+     * @return The constructed FileName.
+     * @throws FileSystemException if an error occurs constructing the FileName.
+     */
+    public FileName resolveName(final FileName root, final String path)
+            throws FileSystemException
+    {
+        return resolveName(root, path, NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Resolves a name, relative to the root.
+     *
+     * @param base the base filename
+     * @param name the name
+     * @param scope the {@link NameScope}
+     * @return The FileName of the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName resolveName(final FileName base, final String name,
+            final NameScope scope) throws FileSystemException
+    {
+        final FileName realBase;
+        if (base != null && VFS.isUriStyle() && base.getType() == FileType.FILE)
+        {
+            realBase = base.getParent();
+        }
+        else
+        {
+            realBase = base;
+        }
+
+        final StringBuffer buffer = new StringBuffer(name);
+
+        // Adjust separators
+        UriParser.fixSeparators(buffer);
+        String scheme = UriParser.extractScheme(buffer.toString());
+
+        // Determine whether to prepend the base path
+        if (name.length() == 0 || (scheme == null && buffer.charAt(0) != FileName.SEPARATOR_CHAR))
+        {
+            // Supplied path is not absolute
+            if (!VFS.isUriStyle())
+            {
+                // when using uris the parent already do have the trailing "/"
+                buffer.insert(0, FileName.SEPARATOR_CHAR);
+            }
+            buffer.insert(0, realBase.getPath());
+        }
+
+        // // UriParser.canonicalizePath(buffer, 0, name.length());
+
+        // Normalise the path
+        FileType fileType = UriParser.normalisePath(buffer);
+
+        // Check the name is ok
+        final String resolvedPath = buffer.toString();
+        if (!AbstractFileName
+                .checkName(realBase.getPath(), resolvedPath, scope))
+        {
+            throw new FileSystemException(
+                    "vfs.provider/invalid-descendent-name.error", name);
+        }
+
+        String fullPath;
+        if (scheme != null)
+        {
+            fullPath = resolvedPath;
+        }
+        else
+        {
+            scheme = realBase.getScheme();
+            fullPath = realBase.getRootURI() + resolvedPath;
+        }
+        final FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider != null)
+        {
+            // todo: extend the filename parser to be able to parse
+            // only a pathname and take the missing informations from
+            // the base. Then we can get rid of the string operation.
+            // // String fullPath = base.getRootURI() +
+            // resolvedPath.substring(1);
+
+            return provider.parseUri(realBase, fullPath);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider - if possible
+            if (defaultProvider != null)
+            {
+                return defaultProvider.parseUri(realBase, fullPath);
+            }
+        }
+
+        // todo: avoid fallback to this point
+        // this happens if we have a virtual filesystem (no provider for scheme)
+        return ((AbstractFileName) realBase).createName(resolvedPath, fileType);
+    }
+
+    /**
+     * Resolve the uri to a filename.
+     * @param uri The URI to resolve.
+     * @return The FileName of the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName resolveURI(String uri) throws FileSystemException
+    {
+        UriParser.checkUriEncoding(uri);
+
+        if (uri == null)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        // Extract the scheme
+        final String scheme = UriParser.extractScheme(uri);
+        if (scheme != null)
+        {
+            // An absolute URI - locate the provider
+            final FileProvider provider = (FileProvider) providers.get(scheme);
+            if (provider != null)
+            {
+                return provider.parseUri(null, uri);
+            }
+
+            // Otherwise, assume a local file
+        }
+
+        // Handle absolute file names
+        if (localFileProvider != null
+                && localFileProvider.isAbsoluteLocalName(uri))
+        {
+            return localFileProvider.parseUri(null, uri);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider
+            if (defaultProvider == null)
+            {
+                throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                        new Object[] {scheme, uri});
+            }
+            return defaultProvider.parseUri(null, uri);
+        }
+
+        // Assume a relative name - use the supplied base file
+        if (baseFile == null)
+        {
+            throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
+        }
+
+        return resolveName(baseFile.getName(), uri, NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Converts a local file into a {@link FileObject}.
+     * @param file The input File.
+     * @return the create FileObject
+     * @throws FileSystemException if an error occurs creating the file naem.
+     */
+    public FileObject toFileObject(final File file) throws FileSystemException
+    {
+        return getLocalFileProvider().findLocalFile(file);
+    }
+
+    /**
+     * Creates a layered file system.
+     * @param scheme The scheme to use.
+     * @param file The FileObject.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final String scheme,
+            final FileObject file) throws FileSystemException
+    {
+        final FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-provider.error",
+                    new Object[] {scheme, file});
+        }
+        return provider.createFileSystem(scheme, file, file.getFileSystem().getFileSystemOptions());
+    }
+
+    /**
+     * Creates a layered file system.
+     * @param file The FileObject to use.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final FileObject file)
+            throws FileSystemException
+    {
+        final String scheme = map.getScheme(file);
+        if (scheme == null)
+        {
+            throw new FileSystemException(
+                    "vfs.impl/no-provider-for-file.error", file);
+        }
+
+        return createFileSystem(scheme, file);
+    }
+
+    /**
+     * Determines if a layered file system can be created for a given file.
+     *
+     * @param file The file to check for.
+     * @return true if the FileSystem can be created.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean canCreateFileSystem(final FileObject file)
+            throws FileSystemException
+    {
+        return map.getScheme(file) != null;
+    }
+
+    /**
+     * Creates a virtual file system.
+     * @param rootFile The FileObject to use.
+     * @return The FileObject in the VirtualFileSystem.
+     * @throws FileSystemException if an error occurs creating the file.
+     */
+    public FileObject createVirtualFileSystem(final FileObject rootFile)
+            throws FileSystemException
+    {
+        return vfsProvider.createFileSystem(rootFile);
+    }
+
+    /**
+     * Creates an empty virtual file system.
+     * @param rootUri The URI to use as the root of the FileSystem.
+     * @return A FileObject in the virtual FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createVirtualFileSystem(final String rootUri)
+            throws FileSystemException
+    {
+        return vfsProvider.createFileSystem(rootUri);
+    }
+
+    /**
+     * Locates the local file provider.
+     * @return The LocalFileProvider.
+     * @throws FileSystemException if an error occurs.
+     */
+    private LocalFileProvider getLocalFileProvider() throws FileSystemException
+    {
+        if (localFileProvider == null)
+        {
+            throw new FileSystemException(
+                    "vfs.impl/no-local-file-provider.error");
+        }
+        return localFileProvider;
+    }
+
+    /**
+     * Get the URLStreamHandlerFactory.
+     * @return The URLStreamHandlerFactory.
+     */
+    public URLStreamHandlerFactory getURLStreamHandlerFactory()
+    {
+        return new VfsStreamHandlerFactory();
+    }
+
+    /**
+     * Closes the given filesystem.<br />
+     * If you use VFS as singleton it is VERY dangerous to call this method
+     * @param filesystem The FileSystem to close.
+     */
+    public void closeFileSystem(FileSystem filesystem)
+    {
+        // inform the cache ...
+        getFilesCache().clear(filesystem);
+
+        // just in case the cache didnt call _closeFileSystem
+        _closeFileSystem(filesystem);
+    }
+
+    /**
+     * Closes the given filesystem.<br />
+     * If you use VFS as singleton it is VERY dangerous to call this method
+     * @param filesystem The FileSystem to close.
+     */
+    public void _closeFileSystem(FileSystem filesystem)
+    {
+        FileProvider provider = (FileProvider) providers.get(filesystem
+                .getRootName().getScheme());
+        if (provider != null)
+        {
+            ((AbstractFileProvider) provider).closeFileSystem(filesystem);
+        }
+    }
+
+    /**
+     * This is an internal class because it needs access to the private member
+     * providers.
+     */
+    final class VfsStreamHandlerFactory implements URLStreamHandlerFactory
+    {
+        public URLStreamHandler createURLStreamHandler(final String protocol)
+        {
+            FileProvider provider = (FileProvider) providers.get(protocol);
+            if (provider != null)
+            {
+                return new DefaultURLStreamHandler(context);
+            }
+
+            // Route all other calls to the default URLStreamHandlerFactory
+            return new URLStreamHandlerProxy();
+        }
+    }
+
+    /**
+     * Get the schemes currently available.
+     * @return The array of scheme names.
+     */
+    public String[] getSchemes()
+    {
+        String[] schemes = new String[providers.size()];
+        providers.keySet().toArray(schemes);
+        return schemes;
+    }
+
+    /**
+     * Get the capabilities for a given scheme.
+     *
+     * @param scheme The scheme to located.
+     * @return A Collection of capabilities.
+     * @throws FileSystemException if the given scheme is not konwn
+     */
+    public Collection getProviderCapabilities(final String scheme)
+            throws FileSystemException
+    {
+        FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                    new Object[] {scheme});
+        }
+
+        return provider.getCapabilities();
+    }
+
+    /**
+     * Get the configuration builder for the given scheme.
+     * @param scheme The scheme to locate.
+     * @return The FileSystemConfigBuilder for the scheme.
+     * @throws FileSystemException if the given scheme is not konwn
+     */
+    public FileSystemConfigBuilder getFileSystemConfigBuilder(final String scheme)
+            throws FileSystemException
+    {
+        FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-scheme.error", new Object[] {scheme});
+        }
+
+        return provider.getConfigBuilder();
+    }
+
+    // -- OPERATIONS --
+
+    /**
+     * Adds the specified FileOperationProvider for the specified scheme.
+     * Several FileOperationProvider's might be registered for the same scheme.
+     * For example, for "file" scheme we can register SvnWsOperationProvider and
+     * CvsOperationProvider.
+     *
+     * @param scheme The scheme the provider should be registered for.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addOperationProvider(final String scheme,
+            final FileOperationProvider operationProvider)
+            throws FileSystemException
+    {
+        addOperationProvider(new String[] {scheme}, operationProvider);
+    }
+
+    /**
+     * @see FileSystemManager#addOperationProvider(String,
+     *      org.apache.commons.vfs.operations.FileOperationProvider)
+     *
+     * @param schemes The array of schemes the provider should apply to.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void addOperationProvider(final String[] schemes,
+            final FileOperationProvider operationProvider)
+            throws FileSystemException
+    {
+        for (int i = 0; i < schemes.length; i++)
+        {
+            final String scheme = schemes[i];
+
+            if (!operationProviders.containsKey(scheme))
+            {
+                final List providers = new ArrayList();
+                operationProviders.put(scheme, providers);
+            }
+
+            final List providers = (List) operationProviders.get(scheme);
+
+            if (providers.contains(operationProvider))
+            {
+                throw new FileSystemException(
+                        "vfs.operation/operation-provider-already-added.error", scheme);
+            }
+
+            setupComponent(operationProvider);
+
+            providers.add(operationProvider);
+        }
+    }
+
+    /**
+     * @param scheme
+     *            the scheme for wich we want to get the list af registered
+     *            providers.
+     *
+     * @return the registered FileOperationProviders for the specified scheme.
+     *         If there were no providers registered for the scheme, it returns
+     *         null.
+     *
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileOperationProvider[] getOperationProviders(final String scheme)
+            throws FileSystemException
+    {
+
+        List providers = (List) operationProviders.get(scheme);
+        if (providers == null || providers.size() == 0)
+        {
+            return null;
+        }
+        return (FileOperationProvider[]) providers.toArray(new FileOperationProvider[] {});
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java
new file mode 100644
index 0000000..355a312
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+
+/**
+ * Same as {@link ProviderConfiguration} but for the default provider.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultProviderConfiguration extends ProviderConfiguration
+{
+    public boolean isDefault()
+    {
+        return true;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java
new file mode 100644
index 0000000..db12a2d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+
+import java.io.File;
+
+
+/**
+ * The default context implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+final class DefaultVfsComponentContext
+    implements VfsComponentContext
+{
+    private final DefaultFileSystemManager manager;
+
+    public DefaultVfsComponentContext(final DefaultFileSystemManager manager)
+    {
+        this.manager = manager;
+    }
+
+    /**
+     * Locate a file by name.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String name,
+                                  final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        return manager.resolveFile(baseFile, name, fileSystemOptions);
+    }
+
+    /**
+     * Locate a file by name.
+     */
+    public FileObject resolveFile(final String name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        return manager.resolveFile(name, fileSystemOptions);
+    }
+
+    public FileName parseURI(String uri) throws FileSystemException
+    {
+        return manager.resolveURI(uri);
+    }
+
+    /**
+     * Returns a {@link FileObject} for a local file.
+     */
+    public FileObject toFileObject(File file)
+        throws FileSystemException
+    {
+        return manager.toFileObject(file);
+    }
+
+    /**
+     * Locates a file replicator for the provider to use.
+     */
+    public FileReplicator getReplicator() throws FileSystemException
+    {
+        return manager.getReplicator();
+    }
+
+    /**
+     * Locates a temporary file store for the provider to use.
+     */
+    public TemporaryFileStore getTemporaryFileStore() throws FileSystemException
+    {
+        return manager.getTemporaryFileStore();
+    }
+
+    /**
+     * Returns the filesystem manager for the current context
+     *
+     * @return the filesystem manager
+     */
+    public FileSystemManager getFileSystemManager()
+    {
+        return manager;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java
new file mode 100644
index 0000000..8aa193f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+
+import java.net.FileNameMap;
+import java.net.URLConnection;
+
+/**
+ * The FileContentInfoFilenameFactory.<br>
+ * Uses the filename extension to determine the content-type.<br>
+ * The content-encoding is not resolved.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class FileContentInfoFilenameFactory implements FileContentInfoFactory
+{
+    public FileContentInfo create(FileContent fileContent)
+    {
+        String contentType = null;
+
+        String name = fileContent.getFile().getName().getBaseName();
+        if (name != null)
+        {
+            FileNameMap fileNameMap = URLConnection.getFileNameMap();
+            contentType = fileNameMap.getContentTypeFor(name);
+        }
+
+        return new DefaultFileContentInfo(contentType, null);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java
new file mode 100644
index 0000000..53fdbf2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A helper class that determines the provider to use for a file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+class FileTypeMap
+{
+    private final Map mimeTypeMap = new HashMap();
+    private final Map extensionMap = new HashMap();
+
+    /**
+     * Adds a MIME type mapping.
+     */
+    public void addMimeType(final String mimeType, final String scheme)
+    {
+        mimeTypeMap.put(mimeType, scheme);
+    }
+
+    /**
+     * Adds a filename extension mapping.
+     */
+    public void addExtension(final String extension, final String scheme)
+    {
+        extensionMap.put(extension, scheme);
+    }
+
+    /**
+     * Finds the provider to use to create a filesystem from a given file.
+     */
+    public String getScheme(final FileObject file) throws FileSystemException
+    {
+        // Check the file's mime type for a match
+        final FileContent content = file.getContent();
+        // final String mimeType = (String) content.getAttribute("content-type");
+        final String mimeType = content.getContentInfo().getContentType();
+        if (mimeType != null)
+        {
+            return (String) mimeTypeMap.get(mimeType);
+        }
+
+        // Check the file's extension for a match
+        final String extension = file.getName().getExtension();
+        return (String) extensionMap.get(extension);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/PrivilegedFileReplicator.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/PrivilegedFileReplicator.java
new file mode 100644
index 0000000..747bff2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/PrivilegedFileReplicator.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.VfsComponent;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+
+import java.io.File;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * A file replicator that wraps another file replicator, performing
+ * the replication as a privileged action.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class PrivilegedFileReplicator
+    implements FileReplicator, VfsComponent
+{
+    private final FileReplicator replicator;
+    private final VfsComponent replicatorComponent;
+
+    public PrivilegedFileReplicator(FileReplicator replicator)
+    {
+        this.replicator = replicator;
+        if (replicator instanceof VfsComponent)
+        {
+            replicatorComponent = (VfsComponent) replicator;
+        }
+        else
+        {
+            replicatorComponent = null;
+        }
+    }
+
+    /**
+     * Sets the Logger to use for the component.
+     * @param logger The logger.
+     */
+    public void setLogger(final Log logger)
+    {
+        if (replicatorComponent != null)
+        {
+            replicatorComponent.setLogger(logger);
+        }
+    }
+
+    /**
+     * Sets the context for the replicator.
+     * @param context The component context.
+     */
+    public void setContext(final VfsComponentContext context)
+    {
+        if (replicatorComponent != null)
+        {
+            replicatorComponent.setContext(context);
+        }
+    }
+
+    /**
+     * Initialises the component.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+        if (replicatorComponent != null)
+        {
+            try
+            {
+                AccessController.doPrivileged(new InitAction());
+            }
+            catch (final PrivilegedActionException e)
+            {
+                throw new FileSystemException("vfs.impl/init-replicator.error", null, e);
+            }
+        }
+    }
+
+    /**
+     * Closes the replicator.
+     */
+    public void close()
+    {
+        if (replicatorComponent != null)
+        {
+            AccessController.doPrivileged(new CloseAction());
+        }
+    }
+
+    /**
+     * Creates a local copy of the file, and all its descendents.
+     * @param srcFile The source FileObject.
+     * @param selector The file selector.
+     * @return The replicated file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public File replicateFile(FileObject srcFile, FileSelector selector)
+        throws FileSystemException
+    {
+        try
+        {
+            final ReplicateAction action = new ReplicateAction(srcFile, selector);
+            return (File) AccessController.doPrivileged(action);
+        }
+        catch (final PrivilegedActionException e)
+        {
+            throw new FileSystemException("vfs.impl/replicate-file.error", new Object[]{srcFile.getName()}, e);
+        }
+    }
+
+    /**
+     * An action that initialises the wrapped replicator.
+     */
+    private class InitAction implements PrivilegedExceptionAction
+    {
+        /**
+         * Performs the action.
+         */
+        public Object run() throws Exception
+        {
+            replicatorComponent.init();
+            return null;
+        }
+    }
+
+    /**
+     * An action that replicates a file using the wrapped replicator.
+     */
+    private class ReplicateAction implements PrivilegedExceptionAction
+    {
+        private final FileObject srcFile;
+        private final FileSelector selector;
+
+        public ReplicateAction(final FileObject srcFile,
+                               final FileSelector selector)
+        {
+            this.srcFile = srcFile;
+            this.selector = selector;
+        }
+
+        /**
+         * Performs the action.
+         * @throws Exception if an error occurs.
+         */
+        public Object 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);
+        }
+    }
+
+    /**
+     * An action that closes the wrapped replicator.
+     */
+    private class CloseAction implements PrivilegedAction
+    {
+        /**
+         * Performs the action.
+         */
+        public Object run()
+        {
+            replicatorComponent.close();
+            return null;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/ProviderConfiguration.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/ProviderConfiguration.java
new file mode 100644
index 0000000..db1ae34
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/ProviderConfiguration.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class describes the configuration for a provider.<br>
+ * Used by digester in StandardFileSystemManager
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class ProviderConfiguration
+{
+    private String className;
+    private final List schemes = new ArrayList(10);
+    private final List dependenies = new ArrayList(10);
+
+    public ProviderConfiguration()
+    {
+    }
+
+    public String getClassName()
+    {
+        return className;
+    }
+
+    public void setClassName(String className)
+    {
+        this.className = className;
+    }
+
+    public void setScheme(String scheme)
+    {
+        schemes.add(scheme);
+    }
+
+    public List getSchemes()
+    {
+        return schemes;
+    }
+
+    public void setDependency(String dependency)
+    {
+        dependenies.add(dependency);
+    }
+
+    public List getDependencies()
+    {
+        return dependenies;
+    }
+
+    public boolean isDefault()
+    {
+        return false;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/Resource.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/Resource.java
new file mode 100644
index 0000000..dbdf34c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/Resource.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileUtil;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.jar.Attributes;
+
+/**
+ * Helper class for VFSClassLoader. This represents a resource loaded with
+ * the classloader.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ * @see VFSClassLoader
+ */
+class Resource
+{
+    private final FileObject root;
+    private final FileObject resource;
+    private final FileObject packageFolder;
+    private final String packageName;
+
+    /**
+     * Creates a new instance.
+     *
+     * @param root     The code source FileObject.
+     * @param resource The resource of the FileObject.
+     */
+    public Resource(final String name,
+                    final FileObject root,
+                    final FileObject resource)
+        throws FileSystemException
+    {
+        this.root = root;
+        this.resource = resource;
+        packageFolder = resource.getParent();
+        final int pos = name.lastIndexOf('/');
+        if (pos == -1)
+        {
+            packageName = null;
+        }
+        else
+        {
+            packageName = name.substring(0, pos).replace('/', '.');
+        }
+    }
+
+    /**
+     * Returns the URL of the resource.
+     */
+    public URL getURL() throws FileSystemException
+    {
+        return resource.getURL();
+    }
+
+    /**
+     * Returns the name of the package containing the resource.
+     */
+    public String getPackageName()
+    {
+        return packageName;
+    }
+
+    /**
+     * Returns an attribute of the package containing the resource.
+     */
+    public String getPackageAttribute(final Attributes.Name attrName) throws FileSystemException
+    {
+        return (String) packageFolder.getContent().getAttribute(attrName.toString());
+    }
+
+    /**
+     * Returns the folder for the package containing the resource.
+     */
+    public FileObject getPackageFolder()
+    {
+        return packageFolder;
+    }
+
+    /**
+     * Returns the FileObject of the resource.
+     */
+    public FileObject getFileObject()
+    {
+        return resource;
+    }
+
+    /**
+     * Returns the code source as an URL.
+     */
+    public URL getCodeSourceURL() throws FileSystemException
+    {
+        return root.getURL();
+    }
+
+    /**
+     * Returns the data for this resource as a byte array.
+     */
+    public byte[] getBytes() throws IOException
+    {
+        return FileUtil.getContent(resource);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/StandardFileSystemManager.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/StandardFileSystemManager.java
new file mode 100644
index 0000000..9523454
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/StandardFileSystemManager.java
@@ -0,0 +1,492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.operations.FileOperationProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.util.Messages;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+/**
+ * A {@link org.apache.commons.vfs.FileSystemManager} that configures itself
+ * from an XML (Default: providers.xml) configuration file.<br>
+ * Certain providers are only loaded and available if the dependend library is in your
+ * classpath. You have to configure your debugging facility to log "debug" messages to see
+ * if a provider was skipped due to "unresolved externals".
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class StandardFileSystemManager
+    extends DefaultFileSystemManager
+{
+    private static final String CONFIG_RESOURCE = "providers.xml";
+    private static final String PLUGIN_CONFIG_RESOURCE = "META-INF/vfs-providers.xml";
+
+    private URL configUri;
+    private 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 (MalformedURLException e)
+        {
+            getLogger().warn(e.getLocalizedMessage(), e);
+        }
+    }
+
+    /**
+     * 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.
+     * @param classLoader The ClassLoader.
+     */
+    public void setClassLoader(final ClassLoader classLoader)
+    {
+        this.classLoader = classLoader;
+    }
+
+    /**
+     * Initializes this manager.  Adds the providers and replicator.
+     * @throws FileSystemException if an error occurs.
+     */
+    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);
+
+        /* replaced by findClassLoader
+        if (classLoader == null)
+        {
+            // Use default classloader
+            classLoader = getClass().getClassLoader();
+        }
+        */
+
+        if (configUri == null)
+        {
+            // Use default config
+            final URL url = getClass().getResource(CONFIG_RESOURCE);
+            if (url == null)
+            {
+                throw new FileSystemException("vfs.impl/find-config-file.error", CONFIG_RESOURCE);
+            }
+            configUri = url;
+        }
+
+        // Configure
+        configure(configUri);
+
+        // Configure Plugins
+        configurePlugins();
+
+        // Initialise super-class
+        super.init();
+    }
+
+    /**
+     * Scans the classpath to find any droped plugin.<br />
+     * The plugin-description has to be in /META-INF/vfs-providers.xml
+     * @throws FileSystemException if an error occurs.
+     */
+    protected void configurePlugins() throws FileSystemException
+    {
+        ClassLoader cl = findClassLoader();
+
+        Enumeration enumResources;
+        try
+        {
+            enumResources = cl.getResources(PLUGIN_CONFIG_RESOURCE);
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+
+        while (enumResources.hasMoreElements())
+        {
+            URL url = (URL) enumResources.nextElement();
+            configure(url);
+        }
+    }
+
+    private ClassLoader findClassLoader()
+    {
+        if (classLoader != null)
+        {
+            return classLoader;
+        }
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null)
+        {
+            cl = getClass().getClassLoader();
+        }
+
+        return cl;
+    }
+
+    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 (IOException e)
+                {
+                    getLogger().warn(e.getLocalizedMessage(), e);
+                }
+            }
+        }
+    }
+
+    /**
+     * 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.
+     */
+    private void configure(final String configUri, final InputStream configStream)
+            throws FileSystemException
+    {
+        try
+        {
+            // Load up the config
+            // TODO - validate
+            final DocumentBuilder builder = createDocumentBuilder();
+            final Element config = builder.parse(configStream).getDocumentElement();
+
+            configure(config);
+
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.impl/load-config.error", configUri, e);
+        }
+    }
+
+    /**
+     * 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();
+    }
+
+    /**
+     * Configures this manager from an parsed XML configuration file
+     * @param config The configuration Element.
+     * @throws FileSystemException if an error occurs.
+     */
+    private void configure(final Element config) throws FileSystemException
+    {
+        // Add the providers
+        final NodeList providers = config.getElementsByTagName("provider");
+        final int count = providers.getLength();
+        for (int i = 0; i < count; i++)
+        {
+            final Element provider = (Element) providers.item(i);
+            addProvider(provider, false);
+        }
+
+        // Add the operation providers
+        final NodeList operationProviders = config.getElementsByTagName("operationProvider");
+        for (int i = 0; i < operationProviders.getLength(); i++)
+        {
+            final Element operationProvider = (Element) operationProviders.item(i);
+            addOperationProvider(operationProvider);
+        }
+
+        // Add the default provider
+        final NodeList defProviders = config.getElementsByTagName("default-provider");
+        if (defProviders.getLength() > 0)
+        {
+            final Element provider = (Element) defProviders.item(0);
+            addProvider(provider, true);
+        }
+
+        // Add the mime-type maps
+        final NodeList mimeTypes = config.getElementsByTagName("mime-type-map");
+        for (int i = 0; i < mimeTypes.getLength(); i++)
+        {
+            final Element map = (Element) mimeTypes.item(i);
+            addMimeTypeMap(map);
+        }
+
+        // Add the extension maps
+        final NodeList extensions = config.getElementsByTagName("extension-map");
+        for (int i = 0; i < extensions.getLength(); i++)
+        {
+            final Element map = (Element) extensions.item(i);
+            addExtensionMap(map);
+        }
+    }
+
+    /**
+     * Adds an extension map.
+     * @param map containing the Elements.
+     */
+    private void addExtensionMap(final Element map)
+    {
+        final String extension = map.getAttribute("extension");
+        final String scheme = map.getAttribute("scheme");
+        if (scheme != null && scheme.length() > 0)
+        {
+            addExtensionMap(extension, scheme);
+        }
+    }
+
+    /**
+     * Adds a mime-type map.
+     * @param map containing the Elements.
+     */
+    private void addMimeTypeMap(final Element map)
+    {
+        final String mimeType = map.getAttribute("mime-type");
+        final String scheme = map.getAttribute("scheme");
+        addMimeTypeMap(mimeType, scheme);
+    }
+
+    /**
+     * 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.
+     */
+    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 (int i = 0; i < requiredSchemes.length; i++)
+        {
+            final String requiredScheme = requiredSchemes[i];
+            if (!hasProvider(requiredScheme))
+            {
+                final String msg = Messages.getString("vfs.impl/skipping-provider-scheme.debug",
+                    new String[]{classname, requiredScheme});
+                VfsLog.debug(getLogger(), getLogger(), msg);
+                return;
+            }
+        }
+
+        // Make sure all required classes are in classpath
+        final String[] requiredClasses = getRequiredClasses(providerDef);
+        for (int i = 0; i < requiredClasses.length; i++)
+        {
+            final String requiredClass = requiredClasses[i];
+            if (!findClass(requiredClass))
+            {
+                final String msg = Messages.getString("vfs.impl/skipping-provider.debug",
+                    new String[]{classname, requiredClass});
+                VfsLog.debug(getLogger(), getLogger(), msg);
+                return;
+            }
+        }
+
+        // Create and register the provider
+        final FileProvider provider = (FileProvider) createInstance(classname);
+        final String[] schemas = getSchemas(providerDef);
+        if (schemas.length > 0)
+        {
+            addProvider(schemas, provider);
+        }
+
+        // Set as default, if required
+        if (isDefault)
+        {
+            setDefaultProvider(provider);
+        }
+    }
+
+    /**
+     * Adds a operationProvider from a operationProvider definition.
+     */
+    private void addOperationProvider(final Element providerDef) throws FileSystemException
+    {
+        final String classname = providerDef.getAttribute("class-name");
+
+        // Attach only to available schemas
+        final String[] schemas = getSchemas(providerDef);
+        for (int i = 0; i < schemas.length; i++)
+        {
+            final String schema = schemas[i];
+            if (hasProvider(schema))
+            {
+                final FileOperationProvider operationProvider = (FileOperationProvider) createInstance(classname);
+                addOperationProvider(schema, operationProvider);
+            }
+        }
+    }
+
+    /**
+     * Tests if a class is available.
+     */
+    private boolean findClass(final String className)
+    {
+        try
+        {
+            findClassLoader().loadClass(className);
+            return true;
+        }
+        catch (final ClassNotFoundException e)
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Extracts the required classes from a provider definition.
+     */
+    private String[] getRequiredClasses(final Element providerDef)
+    {
+        final ArrayList classes = new ArrayList();
+        final NodeList deps = providerDef.getElementsByTagName("if-available");
+        final int count = deps.getLength();
+        for (int i = 0; i < count; i++)
+        {
+            final Element dep = (Element) deps.item(i);
+            String className = dep.getAttribute("class-name");
+            if (className != null && className.length() > 0)
+            {
+                classes.add(className);
+            }
+        }
+        return (String[]) classes.toArray(new String[classes.size()]);
+    }
+
+    /**
+     * Extracts the required schemes from a provider definition.
+     */
+    private String[] getRequiredSchemes(final Element providerDef)
+    {
+        final ArrayList schemes = new ArrayList();
+        final NodeList deps = providerDef.getElementsByTagName("if-available");
+        final int count = deps.getLength();
+        for (int i = 0; i < count; i++)
+        {
+            final Element dep = (Element) deps.item(i);
+            String scheme = dep.getAttribute("scheme");
+            if (scheme != null && scheme.length() > 0)
+            {
+                schemes.add(scheme);
+            }
+        }
+        return (String[]) schemes.toArray(new String[schemes.size()]);
+    }
+
+    /**
+     * Extracts the schema names from a provider definition.
+     */
+    private String[] getSchemas(final Element provider)
+    {
+        final ArrayList schemas = new ArrayList();
+        final NodeList schemaElements = provider.getElementsByTagName("scheme");
+        final int count = schemaElements.getLength();
+        for (int i = 0; i < count; i++)
+        {
+            final Element scheme = (Element) schemaElements.item(i);
+            schemas.add(scheme.getAttribute("name"));
+        }
+        return (String[]) schemas.toArray(new String[schemas.size()]);
+    }
+
+    /**
+     * Creates a provider.
+     */
+    private Object createInstance(final String className)
+        throws FileSystemException
+    {
+        try
+        {
+            final Class clazz = findClassLoader().loadClass(className);
+            return clazz.newInstance();
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.impl/create-provider.error", className, e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/SynchronizedFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/SynchronizedFileObject.java
new file mode 100644
index 0000000..5fc13af
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/SynchronizedFileObject.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+
+import java.util.List;
+
+/**
+ * This decorator synchronize all access to the FileObject.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class SynchronizedFileObject extends DecoratedFileObject
+{
+        public SynchronizedFileObject(FileObject fileObject)
+        {
+                super(fileObject);
+        }
+
+        public void close() throws FileSystemException
+    {
+        synchronized (this)
+        {
+                    super.close();
+        }
+    }
+
+        public void copyFrom(FileObject srcFile, FileSelector selector) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                super.copyFrom(srcFile, selector);
+        }
+    }
+
+        public void createFile() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                super.createFile();
+        }
+    }
+
+        public void createFolder() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                super.createFolder();
+        }
+    }
+
+        public boolean delete() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.delete();
+        }
+    }
+
+        public int delete(FileSelector selector) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.delete(selector);
+        }
+    }
+
+        public boolean exists() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.exists();
+        }
+    }
+
+        public void findFiles(FileSelector selector, boolean depthwise, List selected) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                super.findFiles(selector, depthwise, selected);
+        }
+    }
+
+        public FileObject[] findFiles(FileSelector selector) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.findFiles(selector);
+        }
+    }
+
+        public FileObject getChild(String name) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.getChild(name);
+        }
+    }
+
+        public FileObject[] getChildren() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.getChildren();
+        }
+    }
+
+        public FileContent getContent() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.getContent();
+        }
+    }
+
+        public FileType getType() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.getType();
+        }
+    }
+
+        public boolean isHidden() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.isHidden();
+        }
+    }
+
+        public boolean isReadable() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.isReadable();
+        }
+    }
+
+        public boolean isWriteable() throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.isWriteable();
+        }
+    }
+
+        public void moveTo(FileObject destFile) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                super.moveTo(destFile);
+        }
+    }
+
+        public FileObject resolveFile(String name, NameScope scope) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.resolveFile(name, scope);
+        }
+    }
+
+        public FileObject resolveFile(String path) throws FileSystemException
+        {
+        synchronized (this)
+        {
+                return super.resolveFile(path);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/URLStreamHandlerProxy.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/URLStreamHandlerProxy.java
new file mode 100644
index 0000000..e044dfb
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/URLStreamHandlerProxy.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * A proxy for URLs that are supported by the standard stream handler factory.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+class URLStreamHandlerProxy
+    extends URLStreamHandler
+{
+    protected URLConnection openConnection(final URL url)
+        throws IOException
+    {
+        final URL proxyURL = new URL(url.toExternalForm());
+        return proxyURL.openConnection();
+    }
+
+    protected void parseURL(final URL u,
+                            final String spec,
+                            final int start,
+                            final int limit)
+    {
+        try
+        {
+            final URL url = new URL(u, spec);
+            setURL(u, url.getProtocol(), url.getHost(),
+                url.getPort(), url.getAuthority(), url.getUserInfo(),
+                url.getFile(), url.getQuery(), url.getRef());
+        }
+        catch (MalformedURLException mue)
+        {
+            //We retrow this as a simple runtime exception.
+            //It is retrown in URL as a MalformedURLException anyway.
+            throw new RuntimeException(mue.getMessage());
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VFSClassLoader.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VFSClassLoader.java
new file mode 100644
index 0000000..47cb1da
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VFSClassLoader.java
@@ -0,0 +1,414 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.NameScope;
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.SecureClassLoader;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+
+
+/**
+ * A class loader that can load classes and resources from a search path
+ * VFS FileObjects refering both to folders and JAR files. Any FileObject
+ * of type FileType.FILE is asumed to be a JAR and is opened
+ * by creating a layered file system with the "jar" scheme.
+ * TODO - Test this with signed Jars and a SecurityManager.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ * @see FileSystemManager#createFileSystem
+ */
+public class VFSClassLoader extends SecureClassLoader
+{
+    private final ArrayList resources = new ArrayList();
+
+    /**
+     * Constructors a new VFSClassLoader for the given file.
+     *
+     * @param file    the file to load the classes and resources from.
+     * @param manager the FileManager to use when trying create a layered Jar file
+     *                system.
+     * @throws FileSystemException if an error occurs.
+     */
+    public VFSClassLoader(final FileObject file,
+                          final FileSystemManager manager)
+        throws FileSystemException
+    {
+        this(new FileObject[]{file}, manager, null);
+    }
+
+    /**
+     * Constructors a new VFSClassLoader for the given file.
+     *
+     * @param file    the file to load the classes and resources from.
+     * @param manager the FileManager to use when trying create a layered Jar file
+     *                system.
+     * @param parent  the parent class loader for delegation.
+     * @throws FileSystemException if an error occurs.
+     */
+    public VFSClassLoader(final FileObject file,
+                          final FileSystemManager manager,
+                          final ClassLoader parent)
+        throws FileSystemException
+    {
+        this(new FileObject[]{file}, manager, parent);
+    }
+
+    /**
+     * Constructors a new VFSClassLoader for the given files.  The files will
+     * be searched in the order specified.
+     *
+     * @param files   the files to load the classes and resources from.
+     * @param manager the FileManager to use when trying create a layered Jar file
+     *                system.
+     * @throws FileSystemException if an error occurs.
+     */
+    public VFSClassLoader(final FileObject[] files,
+                          final FileSystemManager manager)
+        throws FileSystemException
+    {
+        this(files, manager, null);
+    }
+
+    /**
+     * Constructors a new VFSClassLoader for the given FileObjects.
+     * The FileObjects will be searched in the order specified.
+     *
+     * @param files   the FileObjects to load the classes and resources from.
+     * @param manager the FileManager to use when trying create a layered Jar file
+     *                system.
+     * @param parent  the parent class loader for delegation.
+     * @throws FileSystemException if an error occurs.
+     */
+    public VFSClassLoader(final FileObject[] files,
+                          final FileSystemManager manager,
+                          final ClassLoader parent) throws FileSystemException
+    {
+        super(parent);
+        addFileObjects(manager, files);
+    }
+
+    /**
+     * Provide access to the file objects this class loader represents.
+     * @return An array of FileObjects.
+     */
+    public FileObject[] getFileObjects()
+    {
+        return (FileObject[]) resources.toArray(new FileObject[resources.size()]);
+    }
+
+    /**
+     * Appends the specified FileObjects to the list of FileObjects to search
+     * for classes and resources.
+     *
+     * @param manager The FileSystemManager.
+     * @param files the FileObjects to append to the search path.
+     * @throws FileSystemException if an error occurs.
+     */
+    private void addFileObjects(final FileSystemManager manager,
+                                final FileObject[] files) throws FileSystemException
+    {
+        for (int i = 0; i < files.length; i++)
+        {
+            FileObject file = files[i];
+            if (!file.exists())
+            {
+                // Does not exist - skip
+                continue;
+            }
+
+            // TODO - use federation instead
+            if (manager.canCreateFileSystem(file))
+            {
+                // Use contents of the file
+                file = manager.createFileSystem(file);
+            }
+
+            resources.add(file);
+        }
+    }
+
+    /**
+     * Finds and loads the class with the specified name from the search
+     * path.
+     *
+     * @throws ClassNotFoundException if the class is not found.
+     */
+    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);
+        }
+    }
+
+    /**
+     * Loads and verifies the class with name and located with res.
+     */
+    private Class defineClass(final String name, final Resource res)
+        throws IOException
+    {
+        final URL url = res.getCodeSourceURL();
+        final String pkgName = res.getPackageName();
+        if (pkgName != null)
+        {
+            final Package pkg = getPackage(pkgName);
+            if (pkg != null)
+            {
+                if (pkg.isSealed())
+                {
+                    if (!pkg.isSealed(url))
+                    {
+                        throw new FileSystemException("vfs.impl/pkg-sealed-other-url", pkgName);
+                    }
+                }
+                else
+                {
+                    if (isSealed(res))
+                    {
+                        throw new FileSystemException("vfs.impl/pkg-sealing-unsealed", pkgName);
+                    }
+                }
+            }
+            else
+            {
+                definePackage(pkgName, res);
+            }
+        }
+
+        final byte[] bytes = res.getBytes();
+        final Certificate[] certs =
+            res.getFileObject().getContent().getCertificates();
+        final CodeSource cs = new CodeSource(url, certs);
+        return defineClass(name, bytes, 0, bytes.length, cs);
+    }
+
+    /**
+     * 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
+    {
+        // TODO - check for MANIFEST_ATTRIBUTES capability first
+        final String specTitle = res.getPackageAttribute(Name.SPECIFICATION_TITLE);
+        final String specVendor = res.getPackageAttribute(Attributes.Name.SPECIFICATION_VENDOR);
+        final String specVersion = res.getPackageAttribute(Name.SPECIFICATION_VERSION);
+        final String implTitle = res.getPackageAttribute(Name.IMPLEMENTATION_TITLE);
+        final String implVendor = res.getPackageAttribute(Name.IMPLEMENTATION_VENDOR);
+        final String implVersion = res.getPackageAttribute(Name.IMPLEMENTATION_VERSION);
+
+        final URL sealBase;
+        if (isSealed(res))
+        {
+            sealBase = res.getCodeSourceURL();
+        }
+        else
+        {
+            sealBase = null;
+        }
+
+        return definePackage(name, specTitle, specVersion, specVendor,
+            implTitle, implVersion, implVendor, sealBase);
+    }
+
+    /**
+     * 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.
+     */
+    protected PermissionCollection getPermissions(final CodeSource cs)
+    {
+        try
+        {
+            final String url = cs.getLocation().toString();
+            FileObject file = lookupFileObject(url);
+            if (file == null)
+            {
+                return super.getPermissions(cs);
+            }
+
+            FileObject parentLayer = file.getFileSystem().getParentLayer();
+            if (parentLayer == null)
+            {
+                return super.getPermissions(cs);
+            }
+
+            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 (Enumeration elem = src.elements(); elem.hasMoreElements();)
+        {
+            final Permission 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)
+    {
+        final Iterator it = resources.iterator();
+        while (it.hasNext())
+        {
+            final FileObject object = (FileObject) it.next();
+            if (name.equals(object.getName().getURI()))
+            {
+                return object;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Finds the resource with the specified name from the search path.
+     * This returns null if the resource is not found.
+     * @param name The resource name.
+     * @return The URL that matches the resource.
+     */
+    protected URL findResource(final String name)
+    {
+        try
+        {
+            final Resource res = loadResource(name);
+            if (res != null)
+            {
+                return res.getURL();
+            }
+        }
+        catch (final Exception mue)
+        {
+            // Ignore
+            // TODO - report?
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns an Enumeration of all the resources in the search path
+     * with the specified name.
+     * TODO - Implement this.
+     * @param name The resources to find.
+     * @return An Enumeration of the resources associated with the name.
+     */
+    protected Enumeration findResources(final String name)
+    {
+        return new Enumeration()
+        {
+            public boolean hasMoreElements()
+            {
+                return false;
+            }
+
+            public Object nextElement()
+            {
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Searches through the search path of for the first class or resource
+     * with specified name.
+     * @param name The resource to load.
+     * @return The Resource.
+     * @throws FileSystemException if an error occurs.
+     */
+    private Resource loadResource(final String name) throws FileSystemException
+    {
+        final Iterator it = resources.iterator();
+        while (it.hasNext())
+        {
+            final FileObject baseFile = (FileObject) it.next();
+            final FileObject file =
+                baseFile.resolveFile(name, NameScope.DESCENDENT_OR_SELF);
+            if (file.exists())
+            {
+                return new Resource(name, baseFile, file);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileName.java
new file mode 100644
index 0000000..e58f2d5
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileName.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileName;
+
+/**
+ * A simple Filename to hold the scheme for to be created virtual filesytsem.
+ *
+ * @author imario@apache.org
+ * @version $Revision$ $Date$
+ */
+public class VirtualFileName extends AbstractFileName
+{
+    public VirtualFileName(final String scheme, final String absPath, final FileType type)
+    {
+        super(scheme, absPath, type);
+    }
+
+    public FileName createName(String absPath, FileType type)
+    {
+        return new VirtualFileName(getScheme(), absPath, type);
+    }
+
+    protected void appendRootUri(StringBuffer buffer, boolean addPassword)
+    {
+        buffer.append(getScheme());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileProvider.java
new file mode 100644
index 0000000..b55651a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractVfsContainer;
+
+
+/**
+ * A virtual filesystem provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class VirtualFileProvider
+    extends AbstractVfsContainer
+{
+    /**
+     * Creates a virtual file system, with the supplied file as its root.
+     * @param rootFile The root of the file system.
+     * @return A FileObject in the FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final FileObject rootFile)
+        throws FileSystemException
+    {
+        final FileName rootName =
+            getContext().getFileSystemManager().resolveName(rootFile.getName(), FileName.ROOT_PATH);
+        // final FileName rootName =
+        //    new BasicFileName(rootFile.getName(), FileName.ROOT_PATH);
+        final VirtualFileSystem fs = new VirtualFileSystem(rootName, rootFile.getFileSystem().getFileSystemOptions());
+        addComponent(fs);
+        fs.addJunction(FileName.ROOT_PATH, rootFile);
+        return fs.getRoot();
+    }
+
+    /**
+     * Creates an empty virtual file system.
+     * @param rootUri The root of the file system.
+     * @return A FileObject in the FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final String rootUri) throws FileSystemException
+    {
+        final FileName rootName =
+            new VirtualFileName(rootUri, FileName.ROOT_PATH, FileType.FOLDER);
+        // final FileName rootName =
+        //    new BasicFileName(rootUri, FileName.ROOT_PATH);
+        final VirtualFileSystem fs = new VirtualFileSystem(rootName, null);
+        addComponent(fs);
+        return fs.getRoot();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileSystem.java
new file mode 100644
index 0000000..cab0717
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/VirtualFileSystem.java
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.DelegateFileObject;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A logical file system, made up of set of junctions, or links, to files from
+ * other file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Handle nested junctions.
+ */
+public class VirtualFileSystem
+    extends AbstractFileSystem
+{
+    private final Map junctions = new HashMap();
+
+    public VirtualFileSystem(final FileName rootName, final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+    }
+
+    /**
+     * Adds the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        // TODO - this isn't really true
+        caps.add(Capability.ATTRIBUTES);
+        caps.add(Capability.CREATE);
+        caps.add(Capability.DELETE);
+        caps.add(Capability.GET_TYPE);
+        caps.add(Capability.JUNCTIONS);
+        caps.add(Capability.GET_LAST_MODIFIED);
+        caps.add(Capability.SET_LAST_MODIFIED_FILE);
+        caps.add(Capability.SET_LAST_MODIFIED_FOLDER);
+        caps.add(Capability.LIST_CHILDREN);
+        caps.add(Capability.READ_CONTENT);
+        caps.add(Capability.SIGNING);
+        caps.add(Capability.WRITE_CONTENT);
+        caps.add(Capability.APPEND_CONTENT);
+    }
+
+    /**
+     * Creates a file object.  This method is called only if the requested
+     * file is not cached.
+     */
+    protected FileObject createFile(final FileName 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 = (FileObject) 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.
+     * @param targetFile The target file to base the junction on.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void addJunction(final String junctionPoint,
+                            final FileObject targetFile)
+        throws FileSystemException
+    {
+        final FileName junctionName = getFileSystemManager().resolveName(getRootName(), junctionPoint);
+
+        // Check for nested junction - these are not supported yet
+        if (getJunctionForFile(junctionName) != null)
+        {
+            throw new FileSystemException("vfs.impl/nested-junction.error", junctionName);
+        }
+
+        try
+        {
+            // Add to junction table
+            junctions.put(junctionName, targetFile);
+
+            // Attach to file
+            final DelegateFileObject junctionFile = (DelegateFileObject) getFileFromCache(junctionName);
+            if (junctionFile != null)
+            {
+                junctionFile.setFile(targetFile);
+            }
+
+            // Create ancestors of junction point
+            FileName childName = junctionName;
+            boolean done = false;
+            for (FileName parentName = childName.getParent();
+                 !done && parentName != null;
+                 childName = parentName, parentName = parentName.getParent())
+            {
+                DelegateFileObject file = (DelegateFileObject) getFileFromCache(parentName);
+                if (file == null)
+                {
+                    file = new DelegateFileObject(parentName, this, null);
+                    putFileToCache(file);
+                }
+                else
+                {
+                    done = file.exists();
+                }
+
+                // As this is the parent of our junction it has to be a folder
+                file.attachChild(childName, FileType.FOLDER);
+            }
+
+            // TODO - attach all cached children of the junction point to their real file
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.impl/create-junction.error", junctionName, e);
+        }
+    }
+
+    /**
+     * Removes a junction from this file system.
+     * @param junctionPoint The junction to remove.
+     * @throws FileSystemException if an error occurs.
+     */
+    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
+    }
+
+    /**
+     * Locates the junction point for the junction containing the given file.
+     * @param name The FileName.
+     * @return the FileName where the junction occurs.
+     */
+    private FileName getJunctionForFile(final FileName name)
+    {
+        if (junctions.containsKey(name))
+        {
+            // The name points to the junction point directly
+            return name;
+        }
+
+        // Find matching junction
+        for (Iterator iterator = junctions.keySet().iterator(); iterator.hasNext();)
+        {
+            final FileName junctionPoint = (FileName) iterator.next();
+            if (junctionPoint.isDescendent(name))
+            {
+                return junctionPoint;
+            }
+        }
+
+        // None
+        return null;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/package.html
new file mode 100644
index 0000000..f757c7f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The standard VFS implementation.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/providers.xml b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/providers.xml
new file mode 100644
index 0000000..429b896
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/impl/providers.xml
@@ -0,0 +1,141 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<providers>
+    <default-provider class-name="org.apache.commons.vfs.provider.url.UrlFileProvider">
+    </default-provider>
+    <provider class-name="org.apache.commons.vfs.provider.local.DefaultLocalFileProvider">
+        <scheme name="file"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.zip.ZipFileProvider">
+        <scheme name="zip"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.tar.TarFileProvider">
+        <scheme name="tar"/>
+        <if-available class-name="org.apache.commons.vfs.provider.tar.TarInputStream"/>
+    </provider>
+
+    <provider class-name="org.apache.commons.vfs.provider.bzip2.Bzip2FileProvider">
+        <scheme name="bz2"/>
+        <if-available class-name="org.apache.commons.vfs.provider.bzip2.CBZip2InputStream"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.gzip.GzipFileProvider">
+        <scheme name="gz"/>
+    </provider>
+
+    <provider class-name="org.apache.commons.vfs.provider.jar.JarFileProvider">
+        <scheme name="jar"/>
+        <scheme name="sar"/>
+        <scheme name="ear"/>
+        <scheme name="par"/>
+        <scheme name="ejb3"/>
+        <scheme name="war"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.temp.TemporaryFileProvider">
+        <scheme name="tmp"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.ftp.FtpFileProvider">
+        <scheme name="ftp"/>
+        <if-available class-name="org.apache.commons.net.ftp.FTPFile"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.ftps.FtpsFileProvider">
+        <scheme name="ftps"/>
+        <if-available class-name="org.apache.commons.net.ftp.FTPFile"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.http.HttpFileProvider">
+        <scheme name="http"/>
+        <if-available class-name="org.apache.commons.httpclient.HttpClient"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.https.HttpsFileProvider">
+        <scheme name="https"/>
+        <if-available class-name="org.apache.commons.httpclient.HttpClient"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.sftp.SftpFileProvider">
+        <scheme name="sftp"/>
+        <if-available class-name="javax.crypto.Cipher"/>
+        <if-available class-name="com.jcraft.jsch.JSch"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.res.ResourceFileProvider">
+        <scheme name="res"/>
+    </provider>
+        <provider class-name="org.apache.commons.vfs.provider.webdav.WebdavFileProvider">
+        <scheme name="webdav"/>
+        <if-available class-name="org.apache.commons.httpclient.HttpClient"/>
+        <if-available class-name="org.apache.jackrabbit.webdav.client.methods.DavMethod"/>
+    </provider>
+    <!--
+    <provider class-name="org.apache.commons.vfs.provider.svn.SvnFileProvider">
+        <scheme name="svnhttps"/>
+    </provider>
+    -->
+    <!--
+        <provider class-name="org.apache.commons.vfs.provider.tar.TgzFileProvider">
+            <scheme name="tgz"/>
+            <if-available scheme="gz"/>
+            <if-available scheme="tar"/>
+        </provider>
+        <provider class-name="org.apache.commons.vfs.provider.tar.Tbz2FileProvider">
+            <scheme name="tbz2"/>
+            <if-available scheme="bz2"/>
+            <if-available scheme="tar"/>
+        </provider>
+    -->
+    <provider class-name="org.apache.commons.vfs.provider.tar.TarFileProvider">
+        <scheme name="tgz"/>
+        <if-available scheme="gz"/>
+        <if-available scheme="tar"/>
+    </provider>
+    <provider class-name="org.apache.commons.vfs.provider.tar.TarFileProvider">
+        <scheme name="tbz2"/>
+        <if-available scheme="bz2"/>
+        <if-available scheme="tar"/>
+    </provider>
+
+    <provider class-name="org.apache.commons.vfs.provider.ram.RamFileProvider">
+        <scheme name="ram"/>
+    </provider>
+    
+    <extension-map extension="zip" scheme="zip"/>
+    <extension-map extension="tar" scheme="tar"/>
+    <mime-type-map mime-type="application/zip" scheme="zip"/>
+    <mime-type-map mime-type="application/x-tar" scheme="tar"/>
+    <mime-type-map mime-type="application/x-gzip" scheme="gz"/>
+    <!--
+    <mime-type-map mime-type="application/x-tgz" scheme="tgz"/>
+    -->
+    <extension-map extension="jar" scheme="jar"/>
+    <extension-map extension="bz2" scheme="bz2"/>
+    <extension-map extension="gz" scheme="gz"/>
+    <!--
+    <extension-map extension="tgz" scheme="tgz"/>
+    <extension-map extension="tbz2" scheme="tbz2"/>
+    -->
+    <extension-map extension="tgz" scheme="tar"/>
+    <extension-map extension="tbz2" scheme="tar"/>
+
+    <!--
+    <filter-map class-name="org.apache.commons.vfs.content.bzip2.Bzip2Compress">
+        <extension name="bz2"/>
+        <extension name="tbz2"/>
+        <if-available class-name="org.apache.commons.compress.bzip2.CBZip2InputStream"/>
+    </filter-map>
+    <filter-map class-name="org.apache.commons.vfs.content.gzip.GzipCompress">
+        <extension name="gz"/>
+        <extension name="tgz"/>
+        <mime-type name="application/x-tgz" />
+    </filter-map>
+    -->
+</providers>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperation.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperation.java
new file mode 100644
index 0000000..e22037e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperation.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileObject;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public abstract class AbstractFileOperation implements FileOperation
+{
+    /**
+     * FileObject which the FileOperation is operate on.
+     */
+    private final FileObject fileObject;
+
+    /**
+     * @param file The FileObject.
+     */
+    public AbstractFileOperation(final FileObject file)
+    {
+        fileObject = file;
+    }
+
+    /**
+     * @return an instance of FileObject which this FileOperation is operate on.
+     */
+    protected FileObject getFileObject()
+    {
+        return fileObject;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperationProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperationProvider.java
new file mode 100644
index 0000000..ec5850c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/AbstractFileOperationProvider.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileObject;
+
+import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public abstract class AbstractFileOperationProvider implements
+        FileOperationProvider
+{
+
+    /**
+     * Available operations. Operations could be registered for different schemes.
+     * Some operations can work only for "file" scheme, other - for "svnhttp(s)",
+     * "svn", "svnssh", but not for "file", etc. The Map has scheme as a key and
+     * Colleaction of operations that are available for that scheme.
+     */
+    private final Collection operations = new ArrayList();
+
+    /**
+     * Gather available operations for the specified FileObject and put them into
+     * specified operationsList.
+     *
+     * @param operationsList
+     *            the list of available operations for the specivied FileObject.
+     *            The operationList contains classes of available operations, e.g.
+     *            Class objects.
+     * @param file
+     *            the FileObject for which we want to get the list of available
+     *            operations.
+     * @throws org.apache.commons.vfs.FileSystemException
+     *             if list of operations cannto be retrieved.
+     */
+    public final void collectOperations(final Collection operationsList,
+            final FileObject file) throws FileSystemException
+    {
+
+        doCollectOperations(operations, operationsList, file);
+    }
+
+    /**
+     *
+     * @throws FileSystemException
+     */
+    protected abstract void doCollectOperations(
+            final Collection availableOperations, final Collection resultList,
+            final FileObject file) throws FileSystemException;
+
+    /**
+     * @param file
+     *            the FileObject for which we need a operation.
+     * @param operationClass
+     *            the Class which instance we are needed.
+     * @return the requried operation instance.
+     * @throws org.apache.commons.vfs.FileSystemException
+     *             if operation cannot be retrieved.
+     */
+    public final FileOperation getOperation(FileObject file, Class operationClass)
+            throws FileSystemException
+    {
+        Class implementation = lookupOperation(operationClass);
+
+        FileOperation operationInstance = instantiateOperation(file, implementation);
+
+        return operationInstance;
+    }
+
+    /**
+     *
+     * @param operationClass
+     * @return
+     * @throws FileSystemException
+     */
+    protected abstract FileOperation instantiateOperation(final FileObject file,
+            final Class operationClass) throws FileSystemException;
+
+    /**
+     *
+     * @param operationClass
+     * @return never returns null
+     */
+    protected final Class lookupOperation(final Class operationClass)
+            throws FileSystemException
+    {
+        // check validity of passed class
+        if (!FileOperation.class.isAssignableFrom(operationClass))
+        {
+            throw new FileSystemException("vfs.operation/wrong-type.error", operationClass);
+        }
+
+        // find appropriate class
+        Class foundClass = null;
+        Iterator iterator = operations.iterator();
+        while (iterator.hasNext())
+        {
+            Class operation = (Class) iterator.next();
+            if (operationClass.isAssignableFrom(operation))
+            {
+                foundClass = operation;
+                break;
+            }
+        }
+
+        if (foundClass == null)
+        {
+            throw new FileSystemException("vfs.operation/not-found.error", operationClass);
+        }
+
+        return foundClass;
+    }
+
+    /**
+     *
+     * @param operationClass
+     * @throws FileSystemException
+     */
+    protected final void addOperation(final Class 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/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/DefaultFileOperations.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/DefaultFileOperations.java
new file mode 100644
index 0000000..a3d1717
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/DefaultFileOperations.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileObject;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public class DefaultFileOperations implements FileOperations
+{
+    /**
+     *
+     */
+    private final FileSystemManager fsmanager;
+
+    /**
+     *
+     */
+    private final FileObject fileObject;
+
+    /**
+     *
+     * @param file The file.
+     */
+    public DefaultFileOperations(final FileObject file)
+    {
+        fileObject = file;
+
+        fsmanager = file.getFileSystem().getFileSystemManager();
+    }
+
+    /**
+     * @return The operation classes.
+     * @throws FileSystemException If an error occurs.
+     *
+     */
+    public Class[] getOperations() throws FileSystemException
+    {
+
+        final String scheme = fileObject.getURL().getProtocol();
+        final FileOperationProvider[] providers = fsmanager
+                .getOperationProviders(scheme);
+
+        if (providers == null)
+        {
+            return null;
+        }
+
+        final List operations = new ArrayList();
+
+        for (int i = 0; i < providers.length; i++)
+        {
+            FileOperationProvider provider = providers[i];
+
+            provider.collectOperations(operations, fileObject);
+        }
+
+        return (Class[]) operations.toArray(new Class[] {});
+    }
+
+    /**
+     * @param operationClass The Class that performs the operation.
+     * @return The FileOperation.
+     * @throws FileSystemException if an error occurs.
+     *
+     */
+    public FileOperation getOperation(Class operationClass)
+            throws FileSystemException
+    {
+
+        final String scheme = fileObject.getURL().getProtocol();
+        final FileOperationProvider[] providers = fsmanager
+                .getOperationProviders(scheme);
+
+        if (providers == null)
+        {
+            throw new FileSystemException(
+                    "vfs.provider/operation-not-supported.error", operationClass);
+        }
+
+        FileOperation resultOperation = null;
+
+        for (int i = 0; i < providers.length; i++)
+        {
+            FileOperationProvider provider = providers[i];
+
+            resultOperation = provider.getOperation(fileObject, operationClass);
+
+            if (resultOperation != null)
+            {
+                break;
+            }
+        }
+
+        if (resultOperation == null)
+        {
+            throw new FileSystemException(
+                    "vfs.provider/operation-not-supported.error", operationClass);
+        }
+
+        return resultOperation;
+    }
+
+    /**
+     * @param operationClass the operation's class.
+     * @return true if the operation of specified class is supported for current
+     *         FileObject and false otherwise.
+     *
+     * @throws FileSystemException if an error occurs.
+     *
+     */
+    public boolean hasOperation(Class operationClass) throws FileSystemException
+    {
+        Class[] operations = getOperations();
+        if (operations == null)
+        {
+            return false;
+        }
+
+        for (int i = 0; i < operations.length; i++)
+        {
+            Class operation = operations[i];
+            if (operationClass.isAssignableFrom(operation))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperation.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperation.java
new file mode 100644
index 0000000..354eb9e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperation.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * <p>
+ * A FileOperation is an object that brings an extra functions to a FileObject.
+ * The VFS provides the basic functionality to deal with FileObject's. Tha is
+ * create, delete, rename, copy, etc functions. However, if you are working with
+ * FileSystem and its files are, for example, under Version Control System (VCS)
+ * you might want to get an access to the versioning framework and to be able to
+ * manage your files regarding VCS (e.g. commit them, undate, get logs, etc.).
+ * Such type of extended functionality is provided by FileOperation.
+ * </p>
+ * <p>
+ * The FileOperation interface is a genetic interface that should not be
+ * implemented directly. It rather should be extended by other interfaces that
+ * provide some concrete functions.
+ * </p>
+ * <p>
+ * FileOperation is provided by
+ *
+ * @see FileOperationProvider Especially the FileOperationProvider is responsible
+ *      for looking up and instantiating any concrete FileOperation.
+ *      </p>
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface FileOperation
+{
+
+    /**
+     * Performs necessary actions that are related to the concrete
+     * implementation of a FileOperation.
+     *
+     * @throws FileSystemException if an error occurs
+     */
+    void process() throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperationProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperationProvider.java
new file mode 100644
index 0000000..4585b19
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperationProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.util.Collection;
+
+/**
+ * FileOperationProvider is responsible for dealing with FileOperation's.
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface FileOperationProvider
+{
+
+    /**
+     * Gather available operations for the specified FileObject and put them into
+     * specified operationsList.
+     *
+     * @param operationsList
+     *            the list of available operations for the specivied FileObject.
+     *            The operationList contains classes of available operations, e.g.
+     *            Class objects.
+     * @param file
+     *            the FileObject for which we want to get the list of available
+     *            operations.
+     *
+     * @throws FileSystemException
+     *             if list of operations cannto be retrieved.
+     */
+    void collectOperations(final Collection operationsList, final FileObject file)
+            throws FileSystemException;
+
+    /**
+     *
+     * @param file
+     *            the FileObject for which we need a operation.
+     * @param operationClass
+     *            the Class which instance we are needed.
+     * @return the requried operation instance. s
+     * @throws FileSystemException
+     *             if operation cannot be retrieved.
+     */
+    FileOperation getOperation(final FileObject file, final Class operationClass)
+            throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperations.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperations.java
new file mode 100644
index 0000000..4acafd4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/FileOperations.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations;
+
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * FileOperations interface provides API to work with operations.
+ *
+ * @see FileOperation on what a operation in the context of VFS is.
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface FileOperations
+{
+    /**
+     * @return all operations associated with the fileObject
+     * @throws FileSystemException if an error occurs.
+     */
+    Class[] getOperations() throws FileSystemException;
+
+    /**
+     * @param operationClass the operation Class.
+     * @return a operation implementing the given <code>operationClass</code>
+     * @throws FileSystemException if an error occus.
+     */
+    FileOperation getOperation(Class operationClass) throws FileSystemException;
+
+    /**
+     * @param operationClass the operation Class.
+     * @return if a operation <code>operationClass</code> is available
+     * @throws FileSystemException if an error ocurs.
+     */
+    boolean hasOperation(Class operationClass) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/package.html
new file mode 100644
index 0000000..242e71c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>VFS Operations handling.</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsAdd.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsAdd.java
new file mode 100644
index 0000000..b88d55e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsAdd.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsAdd extends FileOperation
+{
+    /**
+     *
+     * @param makedir true if directories should be created, false otherwise.
+     */
+    void setMakedir(final boolean makedir);
+
+    /**
+     *
+     * @param recursive true if subdirectories should be processed.
+     */
+    void setRecursive(final boolean recursive);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCheckout.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCheckout.java
new file mode 100644
index 0000000..101cef6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCheckout.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsCheckout extends FileOperation
+{
+    /**
+     *
+     * @param revision The revision number.
+     */
+    void setRevision(final long revision);
+
+    /**
+     *
+     * @param recursive true if directories should be traversed.
+     */
+    void setRecursive(final boolean recursive);
+
+    /**
+     *
+     * @param targetDir directory under which retrieved files should be placed.
+     */
+    void setTargetDirectory(final FileObject targetDir);
+
+    /**
+     * @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 setExport(final boolean export);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommit.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommit.java
new file mode 100644
index 0000000..c9cfc58
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommit.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsCommit extends FileOperation
+{
+
+    /**
+     *
+     * @param isRecursive true if directories should be traversed.
+     */
+    void setRecursive(final boolean isRecursive);
+
+    /**
+     *
+     * @param message The message.
+     */
+    void setMessage(final String message);
+
+    /**
+     *
+     * @param listener Listener that is given control when a commit occurs.
+     */
+    void addCommitListener(final VcsCommitListener listener);
+
+    /**
+     *
+     * @param listener The Listener.
+     */
+    void removeCommitListener(final VcsCommitListener listener);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommitListener.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommitListener.java
new file mode 100644
index 0000000..9986db7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsCommitListener.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsCommitListener
+{
+    /**
+     *
+     * @param path The path.
+     * @param contentStatus takes one of the values as defined in the
+     * @see VcsStatus constants.
+     */
+    void commited(final String path, final int contentStatus);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsDelete.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsDelete.java
new file mode 100644
index 0000000..c44fe29
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsDelete.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsDelete extends FileOperation
+{
+    /**
+     *
+     * @param force true if the delete should be unconditional.
+     */
+    void setForce(final boolean force);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLog.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLog.java
new file mode 100644
index 0000000..e173ac1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLog.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsLog extends FileOperation
+{
+    /**
+     *
+     * @param startRev The start revision.
+     */
+    void setStartRevision(final long startRev);
+
+    /**
+     *
+     * @param endRev The end revision.
+     */
+    void setEndRevision(final long endRev);
+
+    /**
+     *
+     * @param handler The LogEntry handler.
+     */
+    void setLogEntryHandler(final VcsLogEntryHandler handler);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntry.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntry.java
new file mode 100644
index 0000000..fe7677e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntry.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import java.util.Calendar;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public class VcsLogEntry
+{
+    /**
+     *
+     */
+    private final String author;
+
+    /**
+     * Revision.
+     */
+    private final long revision;
+
+    /**
+     * Message.
+     */
+    private final String message;
+
+    /**
+     * Date.
+     */
+    private final Calendar date;
+
+    /**
+     * Path.
+     */
+    private final String path;
+
+    /**
+     *
+     * @param author The author.
+     * @param revision The revision.
+     * @param message The message.
+     * @param date The date.
+     * @param path The path.
+     */
+    public VcsLogEntry(final String author, final long revision,
+            final String message, final Calendar date, final String path)
+    {
+        this.author = author;
+        this.revision = revision;
+        this.message = message;
+        this.date = date;
+        this.path = path;
+    }
+
+    /**
+     *
+     * @return The author.
+     */
+    public String getAuthor()
+    {
+        return author;
+    }
+
+    /**
+     *
+     * @return The revision.
+     */
+    public long getRevision()
+    {
+        return revision;
+    }
+
+    /**
+     *
+     * @return The message.
+     */
+    public String getMessage()
+    {
+        return message;
+    }
+
+    /**
+     *
+     * @return The date.
+     */
+    public Calendar getDate()
+    {
+        return date;
+    }
+
+    /**
+     *
+     * @return The path.
+     */
+    public String getPath()
+    {
+        return path;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntryHandler.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntryHandler.java
new file mode 100644
index 0000000..79e73d9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsLogEntryHandler.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsLogEntryHandler
+{
+    /**
+     *
+     * @param entry The log entry.
+     * @throws FileSystemException if an error occurs.
+     */
+    void handleLogEntry(final VcsLogEntry entry) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsModifyListener.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsModifyListener.java
new file mode 100644
index 0000000..be66a5b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsModifyListener.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsModifyListener
+{
+    /**
+     *
+     * @param path The path String.
+     * @param contentStatus The content status.
+     */
+    void modified(final String path, final int contentStatus);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsRevert.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsRevert.java
new file mode 100644
index 0000000..af2afca
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsRevert.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ * <p>
+ * Restores pristine working copy file and cancels all local modifications. In
+ * other words, VcsRevert replaces working copy file with the latest version
+ * from the repository.
+ * </p>
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsRevert extends FileOperation
+{
+    /**
+     *
+     * @param recursive true if children should be processed.
+     */
+    void setRecursive(final boolean recursive);
+
+    /**
+     *
+     * @param listener The Listener to add.
+     */
+    void addModifyListener(final VcsModifyListener listener);
+
+    /**
+     *
+     * @param listener The Listener to remove.
+     */
+    void removeModifyListener(final VcsModifyListener listener);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsStatus.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsStatus.java
new file mode 100644
index 0000000..cf2b2c6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsStatus.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsStatus extends FileOperation
+{
+    int UNKNOWN = -1;
+    int NOT_MODIFIED = 0;
+    int ADDED = 1;
+    int CONFLICTED = 2;
+    int DELETED = 3;
+    int MERGED = 4;
+    int IGNORED = 5;
+    int MODIFIED = 6;
+    int REPLACED = 7;
+    int UNVERSIONED = 8;
+    int MISSING = 9;
+    int OBSTRUCTED = 10;
+    int REVERTED = 11;
+    int RESOLVED = 12;
+    int COPIED = 13;
+    int MOVED = 14;
+    int RESTORED = 15;
+    int UPDATED = 16;
+    int EXTERNAL = 18;
+    int CORRUPTED = 19;
+    int NOT_REVERTED = 20;
+
+    /**
+     *
+     * @return the status of FileObject
+     */
+    int getStatus();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdate.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdate.java
new file mode 100644
index 0000000..0c3caa2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdate.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+import org.apache.commons.vfs.operations.FileOperation;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsUpdate extends FileOperation
+{
+    /**
+     *
+     * @param revision The revision number.
+     */
+    void setRevision(final long revision);
+
+    /**
+     *
+     * @param isRecursive true if recursive.
+     */
+    void setRecursive(final boolean isRecursive);
+
+    /**
+     *
+     * @param listener The UpdateListener.
+     */
+    void addUpdateListener(final VcsUpdateListener listener);
+
+    /**
+     *
+     * @param listener The UpdateListener.
+     */
+    void removeUpdateListener(final VcsUpdateListener listener);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdateListener.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdateListener.java
new file mode 100644
index 0000000..a75795c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/VcsUpdateListener.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.operations.vcs;
+
+/**
+ *
+ * @author Siarhei Baidun
+ * @since 0.1
+ */
+public interface VcsUpdateListener
+{
+    /**
+     *
+     * @param path The path.
+     * @param revision The revision number.
+     * @param contentStatus
+     *            takes one of the values as defined in the
+     * @see VcsStatus constants.
+     */
+    void updated(final String path, final long revision, final int contentStatus);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/package.html
new file mode 100644
index 0000000..73d29c0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>VFS version control operations.</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/readme.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/readme.html
new file mode 100644
index 0000000..8d3ef2a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/operations/vcs/readme.html
@@ -0,0 +1,27 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<html>
+    <body>
+        <p>
+        This package contains common interfaces for Version Control Systems such as
+        SVN, CVS, etc. <br />
+        The implementation of that interfaces it a system-specific deal and all
+        implementations are located in the corresponding packages for those concrete
+        systems.           
+        </p>
+    </body>
+</html>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/package.html
new file mode 100644
index 0000000..fc34de6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The public VFS API.</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileName.java
new file mode 100644
index 0000000..613f730
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileName.java
@@ -0,0 +1,553 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.VFS;
+
+/**
+ * A default file name implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractFileName
+    implements FileName
+{
+
+    private final String scheme;
+    private final String absPath;
+    private FileType type;
+
+    // Cached stuff
+    private String uri;
+    private String baseName;
+    private String rootUri;
+    private String extension;
+    private String decodedAbsPath;
+
+    private boolean calculateHashCode = true;
+    private int calculatedHashCode;
+
+    public AbstractFileName(final String scheme,
+                            final String absPath, FileType type)
+    {
+        this.rootUri = null;
+        this.scheme = scheme;
+        this.type = type;
+        if (absPath != null && absPath.length() > 0)
+        {
+            if (absPath.length() > 1 && absPath.endsWith("/"))
+            {
+                this.absPath = absPath.substring(0, absPath.length() - 1);
+            }
+            else
+            {
+                this.absPath = absPath;
+            }
+        }
+        else
+        {
+            this.absPath = ROOT_PATH;
+        }
+    }
+
+    /**
+     * Returns the hashcode for this name.
+     * @return The hashCode.
+     */
+    public int hashCode()
+    {
+        if (calculateHashCode)
+        {
+            calculatedHashCode = getRootURI().hashCode() ^ getPath().hashCode();
+            calculateHashCode = false;
+        }
+        return calculatedHashCode;
+    }
+
+    /**
+     * Determines if this object is equal to another.
+     * @param obj The object to compare.
+     * @return true if equal, false if not.
+     */
+    public boolean equals(final Object obj)
+    {
+        if (!(obj instanceof AbstractFileName))
+        {
+            return false;
+        }
+        final AbstractFileName name = (AbstractFileName) obj;
+        return getRootURI().equals(name.getRootURI()) && getPath().equals(name.getPath());
+    }
+
+    /**
+     * Implement Comparable.
+     *
+     * @param obj another abstractfilename
+     * @return negative number if less than, 0 if equal, postive if greater than.
+     */
+    public int compareTo(Object obj)
+    {
+        final AbstractFileName name = (AbstractFileName) obj;
+        int ret = getRootURI().compareTo(name.getRootURI());
+        if (ret != 0)
+        {
+            return ret;
+        }
+
+        // return absPath.compareTo(name.absPath);
+        try
+        {
+            return getPathDecoded().compareTo(name.getPathDecoded());
+        }
+        catch (FileSystemException e)
+        {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /**
+     * Returns the URI of the file.
+     * @return the FileName as a URI.
+     */
+    public String toString()
+    {
+        return getURI();
+    }
+
+    /**
+     * Factory method for creating name instances.
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The FileName.
+     */
+    public abstract FileName createName(String absPath, FileType type);
+
+    /**
+     * Builds the root URI for this file name.  Note that the root URI must not
+     * end with a separator character.
+     * @param buffer A StringBuffer to use to construct the URI.
+     * @param addPassword true if the password should be added, false otherwise.
+     */
+    protected abstract void appendRootUri(StringBuffer buffer, boolean addPassword);
+
+    /**
+     * Returns the base name of the file.
+     * @return The base name of the file.
+     */
+    public String getBaseName()
+    {
+        if (baseName == null)
+        {
+            final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
+            if (idx == -1)
+            {
+                baseName = getPath();
+            }
+            else
+            {
+                baseName = getPath().substring(idx + 1);
+            }
+        }
+
+        return baseName;
+    }
+
+    /**
+     * Returns the absolute path of the file, relative to the root of the
+     * file system that the file belongs to.
+     * @return The path String.
+     */
+    public String getPath()
+    {
+        if (VFS.isUriStyle())
+        {
+            return absPath + getUriTrailer();
+        }
+        return absPath;
+    }
+
+    protected String getUriTrailer()
+    {
+        return getType().hasChildren() ? "/" : "";
+    }
+
+    /**
+     * Returns the decoded path.
+     * @return The decoded path String.
+     * @throws FileSystemException If an error occurs.
+     */
+    public String getPathDecoded() throws FileSystemException
+    {
+        if (decodedAbsPath == null)
+        {
+            decodedAbsPath = UriParser.decode(getPath());
+        }
+
+        return decodedAbsPath;
+    }
+
+    /**
+     * Returns the name of the parent of the file.
+     * @return the FileName of the parent.
+     */
+    public FileName getParent()
+    {
+        final String parentPath;
+        final int idx = getPath().lastIndexOf(SEPARATOR_CHAR);
+        if (idx == -1 || idx == getPath().length() - 1)
+        {
+            // No parent
+            return null;
+        }
+        else if (idx == 0)
+        {
+            // Root is the parent
+            parentPath = SEPARATOR;
+        }
+        else
+        {
+            parentPath = getPath().substring(0, idx);
+        }
+        return createName(parentPath, FileType.FOLDER);
+    }
+
+    /**
+     * find the root of the filesystem.
+     * @return The root FileName.
+     */
+    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.
+     */
+    public String getScheme()
+    {
+        return scheme;
+    }
+
+    /**
+     * Returns the absolute URI of the file.
+     * @return The absolute URI of the file.
+     */
+    public String getURI()
+    {
+        if (uri == null)
+        {
+            uri = createURI();
+        }
+        return uri;
+    }
+
+    protected String createURI()
+    {
+        final StringBuffer buffer = new StringBuffer();
+        appendRootUri(buffer, true);
+        buffer.append(getPath());
+        return buffer.toString();
+    }
+
+    /**
+     * Converts a file name to a relative name, relative to this file name.
+     * @param name The FileName.
+     * @return The relative path to the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public String getRelativeName(final FileName name) throws FileSystemException
+    {
+        final String path = name.getPath();
+
+        // Calculate the common prefix
+        final int basePathLen = getPath().length();
+        final int pathLen = path.length();
+
+        // Deal with root
+        if (basePathLen == 1 && pathLen == 1)
+        {
+            return ".";
+        }
+        else if (basePathLen == 1)
+        {
+            return path.substring(1);
+        }
+
+        final int maxlen = Math.min(basePathLen, pathLen);
+        int pos = 0;
+        for (; pos < maxlen && getPath().charAt(pos) == path.charAt(pos); pos++)
+        {
+        }
+
+        if (pos == basePathLen && pos == pathLen)
+        {
+            // Same names
+            return ".";
+        }
+        else if (pos == basePathLen && pos < pathLen && path.charAt(pos) == SEPARATOR_CHAR)
+        {
+            // A descendent of the base path
+            return path.substring(pos + 1);
+        }
+
+        // Strip the common prefix off the path
+        final StringBuffer buffer = new StringBuffer();
+        if (pathLen > 1 && (pos < pathLen || getPath().charAt(pos) != SEPARATOR_CHAR))
+        {
+            // Not a direct ancestor, need to back up
+            pos = getPath().lastIndexOf(SEPARATOR_CHAR, pos);
+            buffer.append(path.substring(pos));
+        }
+
+        // Prepend a '../' for each element in the base path past the common
+        // prefix
+        buffer.insert(0, "..");
+        pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
+        while (pos != -1)
+        {
+            buffer.insert(0, "../");
+            pos = getPath().indexOf(SEPARATOR_CHAR, pos + 1);
+        }
+
+        return buffer.toString();
+    }
+
+    /**
+     * Returns the root URI of the file system this file belongs to.
+     * @return The URI of the root.
+     */
+    public String getRootURI()
+    {
+        if (rootUri == null)
+        {
+            final StringBuffer buffer = new StringBuffer();
+            appendRootUri(buffer, true);
+            buffer.append(SEPARATOR_CHAR);
+            rootUri = buffer.toString().intern();
+        }
+        return rootUri;
+    }
+
+    /**
+     * Returns the depth of this file name, within its file system.
+     * @return The depth of the file name.
+     */
+    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;
+    }
+
+    /**
+     * Returns the extension of this file name.
+     * @return The file extension.
+     */
+    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 filenames 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;
+    }
+
+    /**
+     * Determines if another file name is an ancestor of this file name.
+     * @param ancestor The FileName to check.
+     * @return true if the FileName is an ancestor, false otherwise.
+     */
+    public boolean isAncestor(final FileName ancestor)
+    {
+        if (!ancestor.getRootURI().equals(getRootURI()))
+        {
+            return false;
+        }
+        return checkName(ancestor.getPath(), getPath(), NameScope.DESCENDENT);
+    }
+
+    /**
+     * Determines if another file name is a descendent of this file name.
+     * @param descendent The FileName to check.
+     * @return true if the FileName is a descendent, false otherwise.
+     */
+    public boolean isDescendent(final FileName descendent)
+    {
+        return isDescendent(descendent, NameScope.DESCENDENT);
+    }
+
+    /**
+     * Determines if another file name is a descendent of this file name.
+     * @param descendent The FileName to check.
+     * @param scope The NameScope.
+     * @return true if the FileName is a descendent, false otherwise.
+     */
+    public boolean isDescendent(final FileName descendent,
+                                final NameScope scope)
+    {
+        if (!descendent.getRootURI().equals(getRootURI()))
+        {
+            return false;
+        }
+        return checkName(getPath(), descendent.getPath(), scope);
+    }
+
+    /**
+     * Returns the requested or current type of this name. <br />
+     * <p>
+     * The "requested" type is the one determined during resolving the name. <br/>
+     * In this case the name is a {@link FileType#FOLDER} if it ends with an "/" else
+     * it will be a {@link FileType#FILE}<br/>
+     * </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}
+     */
+    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}
+     * @throws FileSystemException if an error occurs.
+     */
+    void setType(FileType type) throws FileSystemException
+    {
+        if (type != FileType.FOLDER && type != FileType.FILE && type != FileType.FILE_OR_FOLDER)
+        {
+            throw new FileSystemException("vfs.provider/filename-type.error");
+        }
+
+        this.type = type;
+    }
+
+    /**
+     * 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 (!path.startsWith(basePath))
+        {
+            return false;
+        }
+
+        int baseLen = basePath.length();
+        if (VFS.isUriStyle())
+        {
+            // strip the trailing "/"
+            baseLen--;
+        }
+
+        if (scope == NameScope.CHILD)
+        {
+            if (path.length() == baseLen
+                || (baseLen > 1 && path.charAt(baseLen) != SEPARATOR_CHAR)
+                || path.indexOf(SEPARATOR_CHAR, baseLen + 1) != -1)
+            {
+                return false;
+            }
+        }
+        else if (scope == NameScope.DESCENDENT)
+        {
+            if (path.length() == baseLen
+                || (baseLen > 1 && path.charAt(baseLen) != SEPARATOR_CHAR))
+            {
+                return false;
+            }
+        }
+        else if (scope == NameScope.DESCENDENT_OR_SELF)
+        {
+            if (baseLen > 1
+                && path.length() > baseLen
+                && path.charAt(baseLen) != SEPARATOR_CHAR)
+            {
+                return false;
+            }
+        }
+        else if (scope != NameScope.FILE_SYSTEM)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        return true;
+    }
+
+    /**
+     * returns a "friendly path", this is a path without a password.
+     * @return The "friendly" URI.
+     */
+    public String getFriendlyURI()
+    {
+        final StringBuffer buffer = new StringBuffer();
+        appendRootUri(buffer, false);
+        buffer.append(getPath());
+        return buffer.toString();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileNameParser.java
new file mode 100644
index 0000000..580a437
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileNameParser.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+/**
+ * Provides methods to parse a filename into a {@link org.apache.commons.vfs.FileName}.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public abstract class AbstractFileNameParser implements FileNameParser
+{
+    public boolean encodeCharacter(char ch)
+    {
+        return ch == '%';
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileObject.java
new file mode 100644
index 0000000..e0034bd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileObject.java
@@ -0,0 +1,1815 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+
+import org.apache.commons.vfs.operations.DefaultFileOperations;
+import org.apache.commons.vfs.operations.FileOperations;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.commons.vfs.util.RandomAccessMode;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileNotFolderException;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileUtil;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A partial file object implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Revision$ $Date$
+ * @todo Chop this class up - move all the protected methods to several
+ * interfaces, so that structure and content can be separately overridden.
+ * @todo Check caps in methods like getChildren(), etc, and give better error messages
+ * (eg 'this file type does not support listing children', vs 'this is not a folder')
+ */
+public abstract class AbstractFileObject implements FileObject
+{
+    // private static final FileObject[] EMPTY_FILE_ARRAY = {};
+    private static final FileName[] EMPTY_FILE_ARRAY = {};
+
+    private static final int INITIAL_LISTSZ = 5;
+
+    private final AbstractFileName name;
+    private final AbstractFileSystem fs;
+
+    private FileContent content;
+
+    // Cached info
+    private boolean attached;
+    private FileType type;
+    private FileObject parent;
+
+    // Changed to hold only the name of the children and let the object
+    // go into the global files cache
+    // private FileObject[] children;
+    private FileName[] children;
+    private List objects;
+
+    /**
+     * FileServices instance.
+     */
+    private FileOperations operations;
+
+    protected AbstractFileObject(final FileName name,
+                                 final AbstractFileSystem fs)
+    {
+        this.name = (AbstractFileName) name;
+        this.fs = fs;
+        fs.fileObjectHanded(this);
+    }
+
+    /**
+     * Attaches this file object to its file resource.  This method is called
+     * before any of the doBlah() or onBlah() methods.  Sub-classes can use
+     * this method to perform lazy initialisation.
+     * <p/>
+     * This implementation does nothing.
+     */
+    protected void doAttach() throws Exception
+    {
+    }
+
+    /**
+     * Detaches this file object from its file resource.
+     * <p/>
+     * <p>Called when this file is closed.  Note that the file object may be
+     * reused later, so should be able to be reattached.
+     * <p/>
+     * This implementation does nothing.
+     */
+    protected void doDetach() throws Exception
+    {
+    }
+
+    /**
+     * Determines the type of this file.  Must not return null.  The return
+     * value of this method is cached, so the implementation can be expensive.
+     */
+    protected abstract FileType doGetType() throws Exception;
+
+    /**
+     * Determines if this file is hidden.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation always returns false.
+     */
+    protected boolean doIsHidden() throws Exception
+    {
+        return false;
+    }
+
+    /**
+     * Determines if this file can be read.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation always returns true.
+     */
+    protected boolean doIsReadable() throws Exception
+    {
+        return true;
+    }
+
+    /**
+     * Determines if this file can be written to.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation always returns true.
+     */
+    protected boolean doIsWriteable() throws Exception
+    {
+        return true;
+    }
+
+    /**
+     * Lists the children of this file.  Is only called if {@link #doGetType}
+     * returns {@link FileType#FOLDER}.  The return value of this method
+     * is cached, so the implementation can be expensive.<br />
+     * @return a possible empty String array if the file is a directory or null or an exception if the
+     * file is not a directory or can't be read
+     */
+    protected abstract String[] doListChildren() throws Exception;
+
+    /**
+     * Lists the children of this file.  Is only called if {@link #doGetType}
+     * returns {@link FileType#FOLDER}.  The return value of this method
+     * is cached, so the implementation can be expensive.<br>
+     * Other than <code>doListChildren</code> you could return FileObject's to e.g. reinitialize the
+     * type of the file.<br>
+     * (Introduced for Webdav: "permission denied on resource" during getType())
+     */
+    protected FileObject[] doListChildrenResolved() throws Exception
+    {
+        return null;
+    }
+
+    /**
+     * Deletes the file.  Is only called when:
+     * <ul>
+     * <li>{@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <li>{@link #doIsWriteable} returns true.
+     * <li>This file has no children, if a folder.
+     * </ul>
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected void doDelete() throws Exception
+    {
+        throw new FileSystemException("vfs.provider/delete-not-supported.error");
+    }
+
+    /**
+     * Renames the file.  Is only called when:
+     * <ul>
+     * <li>{@link #doIsWriteable} returns true.
+     * </ul>
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        throw new FileSystemException("vfs.provider/rename-not-supported.error");
+    }
+
+    /**
+     * Creates this file as a folder.  Is only called when:
+     * <ul>
+     * <li>{@link #doGetType} returns {@link FileType#IMAGINARY}.
+     * <li>The parent folder exists and is writeable, or this file is the
+     * root of the file system.
+     * </ul>
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        throw new FileSystemException("vfs.provider/create-folder-not-supported.error");
+    }
+
+    /**
+     * Called when the children of this file change.  Allows subclasses to
+     * refresh any cached information about the children of this file.
+     * <p/>
+     * This implementation does nothing.
+     */
+    protected void onChildrenChanged(FileName child, FileType newType) throws Exception
+    {
+    }
+
+    /**
+     * Called when the type or content of this file changes.
+     * <p/>
+     * This implementation does nothing.
+     */
+    protected void onChange() throws Exception
+    {
+    }
+
+    /**
+     * Returns the last modified time of this file.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        throw new FileSystemException("vfs.provider/get-last-modified-not-supported.error");
+    }
+
+    /**
+     * Sets the last modified time of this file.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     *
+     * @return false if it was not possible to change the time
+     */
+    protected boolean doSetLastModTime(final long modtime)
+        throws Exception
+    {
+        doSetLastModifiedTime(modtime);
+        return true;
+    }
+
+    /**
+     * Sets the last modified time of this file.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     *
+     * @deprecated use {@link #doSetLastModTime}
+     */
+    protected void doSetLastModifiedTime(final long modtime)
+        throws Exception
+    {
+        throw new FileSystemException("vfs.provider/set-last-modified-not-supported.error");
+    }
+
+    /**
+     * Returns the attributes of this file.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation always returns an empty map.
+     */
+    protected Map doGetAttributes()
+        throws Exception
+    {
+        return Collections.EMPTY_MAP;
+    }
+
+    /**
+     * Sets an attribute of this file.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected void doSetAttribute(final String atttrName, final Object value)
+        throws Exception
+    {
+        throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
+    }
+
+    /**
+     * Removes an attribute of this file.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     * @returns true if removing the attribute succeed. In this case we remove the attribute from
+     * our cache
+     */
+    protected void doRemoveAttribute(final String atttrName)
+        throws Exception
+    {
+        throw new FileSystemException("vfs.provider/remove-attribute-not-supported.error");
+    }
+
+    /**
+     * Returns the certificates used to sign this file.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation always returns null.
+     */
+    protected Certificate[] doGetCertificates() throws Exception
+    {
+        return null;
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).  Is only called if
+     * {@link #doGetType} returns {@link FileType#FILE}.
+     */
+    protected abstract long doGetContentSize() throws Exception;
+
+    /**
+     * Creates an input stream to read the file content from.  Is only called
+     * if {@link #doGetType} returns {@link FileType#FILE}.
+     * <p/>
+     * <p>It is guaranteed that there are no open output streams for this file
+     * when this method is called.
+     * <p/>
+     * <p>The returned stream does not have to be buffered.
+     */
+    protected abstract InputStream doGetInputStream() throws Exception;
+
+    /**
+     * Creates access to the file for random i/o.  Is only called
+     * if {@link #doGetType} returns {@link FileType#FILE}.
+     * <p/>
+     * <p>It is guaranteed that there are no open output streams for this file
+     * when this method is called.
+     * <p/>
+     */
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        throw new FileSystemException("vfs.provider/random-access-not-supported.error");
+    }
+
+    /**
+     * Creates an output stream to write the file content to.  Is only
+     * called if:
+     * <ul>
+     * <li>{@link #doIsWriteable} returns true.
+     * <li>{@link #doGetType} returns {@link FileType#FILE}, or
+     * {@link #doGetType} returns {@link FileType#IMAGINARY}, and the file's
+     * parent exists and is a folder.
+     * </ul>
+     * <p/>
+     * <p>It is guaranteed that there are no open stream (input or output) for
+     * this file when this method is called.
+     * <p/>
+     * <p>The returned stream does not have to be buffered.
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        throw new FileSystemException("vfs.provider/write-not-supported.error");
+    }
+
+    /**
+     * Returns the URI of the file.
+     * @return The URI of the file.
+     */
+    public String toString()
+    {
+        return name.getURI();
+    }
+
+    /**
+     * Returns the name of the file.
+     * @return The FileName.
+     */
+    public FileName getName()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the file system this file belongs to.
+     * @return The FileSystem this file is associated with.
+     */
+    public FileSystem getFileSystem()
+    {
+        return fs;
+    }
+
+    /**
+     * Returns a URL representation of the file.
+     * @return The URL representation of the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public URL getURL() throws FileSystemException
+    {
+        final StringBuffer buf = new StringBuffer();
+        try
+        {
+            return (URL) AccessController.doPrivileged(new PrivilegedExceptionAction()
+            {
+                public Object run() throws MalformedURLException
+                {
+                    return new URL(UriParser.extractScheme(name.getURI(), buf), "", -1,
+                        buf.toString(), new DefaultURLStreamHandler(fs.getContext(), fs.getFileSystemOptions()));
+                }
+            });
+        }
+        catch (final PrivilegedActionException e)
+        {
+            throw new FileSystemException("vfs.provider/get-url.error", name, e.getException());
+        }
+    }
+
+    /**
+     * Determines if the file exists.
+     * @return true if the file exists, false otherwise,
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean exists() throws FileSystemException
+    {
+        return getType() != FileType.IMAGINARY;
+    }
+
+    /**
+     * Returns the file's type.
+     * @return The FileType.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileType getType() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            attach();
+
+            // VFS-210: get the type only if requested for
+            try
+            {
+                if (type == null)
+                {
+                    setFileType(doGetType());
+                }
+                if (type == null)
+                {
+                    setFileType(FileType.IMAGINARY);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new FileSystemException("vfs.provider/get-type.error", new Object[]{name}, e);
+            }
+
+            return type;
+        }
+    }
+
+    /**
+     * Determines if this file can be read.
+     * @return true if the file is a hidden file, false otherwise.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isHidden() throws FileSystemException
+    {
+        try
+        {
+            if (exists())
+            {
+                return doIsHidden();
+            }
+            else
+            {
+                return false;
+            }
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/check-is-hidden.error", name, exc);
+        }
+    }
+
+    /**
+     * Determines if this file can be read.
+     * @return true if the file can be read, false otherwise.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isReadable() throws FileSystemException
+    {
+        try
+        {
+            if (exists())
+            {
+                return doIsReadable();
+            }
+            else
+            {
+                return false;
+            }
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/check-is-readable.error", name, exc);
+        }
+    }
+
+    /**
+     * Determines if this file can be written to.
+     * @return true if the file can be written to, false otherwise.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isWriteable() throws FileSystemException
+    {
+        try
+        {
+            if (exists())
+            {
+                return doIsWriteable();
+            }
+            else
+            {
+                final FileObject parent = getParent();
+                if (parent != null)
+                {
+                    return parent.isWriteable();
+                }
+                return true;
+            }
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/check-is-writeable.error", name, exc);
+        }
+    }
+
+    /**
+     * Returns the parent of the file.
+     * @return the parent FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getParent() throws FileSystemException
+    {
+        if (this == fs.getRoot())
+        {
+            if (fs.getParentLayer() != null)
+            {
+                // Return the parent of the parent layer
+                return fs.getParentLayer().getParent();
+            }
+            else
+            {
+                // Root file has no parent
+                return null;
+            }
+        }
+
+        synchronized (fs)
+        {
+            // Locate the parent of this file
+            if (parent == null)
+            {
+                parent = fs.resolveFile(name.getParent());
+            }
+        }
+        return parent;
+    }
+
+    /**
+     * Returns the children of the file.
+     * @return an array of FileObjects, one per child.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject[] getChildren() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            // VFS-210
+            if (!getFileSystem().hasCapability(Capability.LIST_CHILDREN))
+            {
+                throw new FileNotFolderException(name);
+            }
+
+            /* VFS-210
+            if (!getType().hasChildren())
+            {
+                throw new FileSystemException("vfs.provider/list-children-not-folder.error", name);
+            }
+            */
+            attach();
+
+            // Use cached info, if present
+            if (children != null)
+            {
+                return resolveFiles(children);
+            }
+
+            // allow the filesystem to return resolved children. e.g. prefill type for webdav
+            FileObject[] childrenObjects;
+            try
+            {
+                childrenObjects = doListChildrenResolved();
+                children = extractNames(childrenObjects);
+            }
+            catch (FileSystemException exc)
+            {
+                // VFS-210
+                throw exc;
+            }
+            catch (Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/list-children.error", new Object[]{name}, exc);
+            }
+
+            if (childrenObjects != null)
+            {
+                return childrenObjects;
+            }
+
+            // List the children
+            final String[] files;
+            try
+            {
+                files = doListChildren();
+            }
+            catch (FileSystemException exc)
+            {
+                // VFS-210
+                throw exc;
+            }
+            catch (Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/list-children.error", new Object[]{name}, exc);
+            }
+
+            if (files == null)
+            {
+                // VFS-210
+                // honor the new doListChildren contract
+                // return null;
+                throw new FileNotFolderException(name);
+            }
+            else if (files.length == 0)
+            {
+                // No children
+                children = EMPTY_FILE_ARRAY;
+            }
+            else
+            {
+                // Create file objects for the children
+                // children = new FileObject[files.length];
+                children = new FileName[files.length];
+                for (int i = 0; i < files.length; i++)
+                {
+                    final String file = files[i];
+                    // children[i] = fs.resolveFile(name.resolveName(file, NameScope.CHILD));
+                    // children[i] = name.resolveName(file, NameScope.CHILD);
+                    children[i] = getFileSystem().getFileSystemManager().resolveName(name, file, NameScope.CHILD);
+                }
+            }
+
+            return resolveFiles(children);
+        }
+    }
+
+    private FileName[] extractNames(FileObject[] objects)
+    {
+        if (objects == null)
+        {
+            return null;
+        }
+
+        FileName[] names = new FileName[objects.length];
+        for (int iterObjects = 0; iterObjects < objects.length; iterObjects++)
+        {
+            names[iterObjects] = objects[iterObjects].getName();
+        }
+
+        return names;
+    }
+
+    private FileObject[] resolveFiles(FileName[] children) throws FileSystemException
+    {
+        if (children == null)
+        {
+            return null;
+        }
+
+        FileObject[] objects = new FileObject[children.length];
+        for (int iterChildren = 0; iterChildren < children.length; iterChildren++)
+        {
+            objects[iterChildren] = resolveFile(children[iterChildren]);
+        }
+
+        return objects;
+    }
+
+    private FileObject resolveFile(FileName child) throws FileSystemException
+    {
+        return fs.resolveFile(child);
+    }
+
+    /**
+     * Returns a child of this file.
+     * @param name The name of the child to locate.
+     * @return The FileObject for the file or null if the child does not exist.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getChild(final String name) throws FileSystemException
+    {
+        // TODO - use a hashtable when there are a large number of children
+        FileObject[] children = getChildren();
+        for (int i = 0; i < children.length; i++)
+        {
+            // final FileObject child = children[i];
+            final FileName child = children[i].getName();
+            // TODO - use a comparator to compare names
+            // if (child.getName().getBaseName().equals(name))
+            if (child.getBaseName().equals(name))
+            {
+                return resolveFile(child);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a child by name.
+     * @param name The name of the child to locate.
+     * @param scope the NameScope.
+     * @return The FileObject for the file or null if the child does not exist.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject resolveFile(final String name, final NameScope scope)
+        throws FileSystemException
+    {
+        // return fs.resolveFile(this.name.resolveName(name, scope));
+        return fs.resolveFile(getFileSystem().getFileSystemManager().resolveName(this.name, name, scope));
+    }
+
+    /**
+     * Finds a file, relative to this file.
+     *
+     * @param path The path of the file to locate.  Can either be a relative
+     *             path, which is resolved relative to this file, or an
+     *             absolute path, which is resolved relative to the file system
+     *             that contains this file.
+     * @return The FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject resolveFile(final String path) throws FileSystemException
+    {
+        final FileName otherName = getFileSystem().getFileSystemManager().resolveName(name, path);
+        return fs.resolveFile(otherName);
+    }
+
+    /**
+     * Deletes this file, once all its children have been deleted
+     *
+     * @return true if this file has been deleted
+     */
+    private boolean deleteSelf() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            /* Its possible to delete a read-only file if you have write-execute access to the directory
+            if (!isWriteable())
+            {
+                throw new FileSystemException("vfs.provider/delete-read-only.error", name);
+            }
+            */
+
+            /* VFS-210
+            if (getType() == FileType.IMAGINARY)
+            {
+                // File does not exist
+                return false;
+            }
+            */
+
+            try
+            {
+                // Delete the file
+                doDelete();
+
+                // Update cached info
+                handleDelete();
+            }
+            catch (final RuntimeException re)
+            {
+                throw re;
+            }
+            catch (final Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/delete.error", new Object[]{name}, exc);
+            }
+
+            return true;
+        }
+    }
+
+    /**
+     * Deletes this file.
+     *
+     * @return true if this object has been deleted
+     * @todo This will not fail if this is a non-empty folder.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean delete() throws FileSystemException
+    {
+        return delete(Selectors.SELECT_SELF) > 0;
+    }
+
+    /**
+     * Deletes this file, and all children.
+     *
+     * @param selector The FileSelector.
+     * @return the number of deleted files.
+     * @throws FileSystemException if an error occurs.
+     */
+    public int delete(final FileSelector selector) throws FileSystemException
+    {
+        int nuofDeleted = 0;
+
+        /* VFS-210
+        if (getType() == FileType.IMAGINARY)
+        {
+            // File does not exist
+            return nuofDeleted;
+        }
+        */
+
+        // Locate all the files to delete
+        ArrayList files = new ArrayList();
+        findFiles(selector, true, files);
+
+        // Delete 'em
+        final int count = files.size();
+        for (int i = 0; i < count; i++)
+        {
+            final AbstractFileObject file = FileObjectUtils.getAbstractFileObject((FileObject) files.get(i));
+            // file.attach();
+
+            // VFS-210: It seems impossible to me that findFiles will return a list with hidden files/directories
+            // in it, else it would not be hidden. Checking for the file-type seems ok in this case
+            // If the file is a folder, make sure all its children have been deleted
+            if (file.getType().hasChildren() && file.getChildren().length != 0)
+            {
+                // Skip - as the selector forced us not to delete all files
+                continue;
+            }
+
+            // Delete the file
+            boolean deleted = file.deleteSelf();
+            if (deleted)
+            {
+                nuofDeleted++;
+            }
+        }
+
+        return nuofDeleted;
+    }
+
+    /**
+     * Creates this file, if it does not exist.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void createFile() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            try
+            {
+                // VFS-210: We do not want to trunc any existing file, checking for its existence is
+                // still required
+                if (exists() && !FileType.FILE.equals(getType()))
+                {
+                    throw new FileSystemException("vfs.provider/create-file.error", name);
+                }
+
+                if (!exists())
+                {
+                    getOutputStream().close();
+                    endOutput();
+                }
+            }
+            catch (final RuntimeException re)
+            {
+                throw re;
+            }
+            catch (final Exception e)
+            {
+                throw new FileSystemException("vfs.provider/create-file.error", name, e);
+            }
+        }
+    }
+
+    /**
+     * Creates this folder, if it does not exist.  Also creates any ancestor
+     * files which do not exist.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void createFolder() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            // VFS-210: we create a folder only if it does not already exist. So this check should be safe.
+            if (getType().hasChildren())
+            {
+                // Already exists as correct type
+                return;
+            }
+            if (getType() != FileType.IMAGINARY)
+            {
+                throw new FileSystemException("vfs.provider/create-folder-mismatched-type.error", name);
+            }
+            /* VFS-210: checking for writeable is not always possible as the security constraint might
+               be more complex
+            if (!isWriteable())
+            {
+                throw new FileSystemException("vfs.provider/create-folder-read-only.error", name);
+            }
+            */
+
+            // Traverse up the heirarchy and make sure everything is a folder
+            final FileObject parent = getParent();
+            if (parent != null)
+            {
+                parent.createFolder();
+            }
+
+            try
+            {
+                // Create the folder
+                doCreateFolder();
+
+                // Update cached info
+                handleCreate(FileType.FOLDER);
+            }
+            catch (final RuntimeException re)
+            {
+                throw re;
+            }
+            catch (final Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/create-folder.error", name, exc);
+            }
+        }
+    }
+
+    /**
+     * Copies another file to this file.
+     * @param file The FileObject to copy.
+     * @param selector The FileSelector.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void copyFrom(final FileObject file, final FileSelector selector)
+        throws FileSystemException
+    {
+        if (!file.exists())
+        {
+            throw new FileSystemException("vfs.provider/copy-missing-file.error", file);
+        }
+        /* we do not alway know if a file is writeable
+        if (!isWriteable())
+        {
+            throw new FileSystemException("vfs.provider/copy-read-only.error", new Object[]{file.getType(),
+            file.getName(), this}, null);
+        }
+        */
+
+        // Locate the files to copy across
+        final ArrayList files = new ArrayList();
+        file.findFiles(selector, false, files);
+
+        // Copy everything across
+        final int count = files.size();
+        for (int i = 0; i < count; i++)
+        {
+            final FileObject srcFile = (FileObject) files.get(i);
+
+            // Determine the destination file
+            final String relPath = file.getName().getRelativeName(srcFile.getName());
+            final FileObject destFile = resolveFile(relPath, NameScope.DESCENDENT_OR_SELF);
+
+            // Clean up the destination file, if necessary
+            if (destFile.exists() && destFile.getType() != srcFile.getType())
+            {
+                // The destination file exists, and is not of the same type,
+                // so delete it
+                // TODO - add a pluggable policy for deleting and overwriting existing files
+                destFile.delete(Selectors.SELECT_ALL);
+            }
+
+            // Copy across
+            try
+            {
+                if (srcFile.getType().hasContent())
+                {
+                    FileUtil.copyContent(srcFile, destFile);
+                }
+                else if (srcFile.getType().hasChildren())
+                {
+                    destFile.createFolder();
+                }
+            }
+            catch (final IOException e)
+            {
+                throw new FileSystemException("vfs.provider/copy-file.error", new Object[]{srcFile, destFile}, e);
+            }
+        }
+    }
+
+    /**
+     * Moves (rename) the file to another one.
+     * @param destFile The target FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void moveTo(FileObject destFile) throws FileSystemException
+    {
+        if (canRenameTo(destFile))
+        {
+            if (!getParent().isWriteable())
+            {
+                throw new FileSystemException("vfs.provider/rename-parent-read-only.error", new FileName[]{getName(),
+                        getParent().getName()});
+            }
+        }
+        else
+        {
+            if (!isWriteable())
+            {
+                throw new FileSystemException("vfs.provider/rename-read-only.error", getName());
+            }
+        }
+
+        if (destFile.exists() && !isSameFile(destFile))
+        {
+            destFile.delete(Selectors.SELECT_ALL);
+            // throw new FileSystemException("vfs.provider/rename-dest-exists.error", destFile.getName());
+        }
+
+        if (canRenameTo(destFile))
+        {
+            // issue rename on same filesystem
+            try
+            {
+                attach();
+                doRename(destFile);
+
+                (FileObjectUtils.getAbstractFileObject(destFile)).handleCreate(getType());
+
+                destFile.close(); // now the destFile is no longer imaginary. force reattach.
+
+                handleDelete(); // fire delete-events. This file-object (src) is like deleted.
+            }
+            catch (final RuntimeException re)
+            {
+                throw re;
+            }
+            catch (final Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/rename.error", new Object[]
+                    {
+                        getName(),
+                        destFile.getName()
+                    }, exc);
+            }
+        }
+        else
+        {
+            // different fs - do the copy/delete stuff
+
+            destFile.copyFrom(this, Selectors.SELECT_SELF);
+
+            if (((destFile.getType().hasContent()
+                    && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE))
+                  || (destFile.getType().hasChildren()
+                    && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FOLDER)))
+                    && getFileSystem().hasCapability(Capability.GET_LAST_MODIFIED))
+            {
+                destFile.getContent().setLastModifiedTime(this.getContent().getLastModifiedTime());
+            }
+
+            deleteSelf();
+        }
+
+    }
+
+    /**
+     * Checks if this fileObject is the same file as <code>destFile</code> just with a different
+     * name.<br />
+     * E.g. for case insensitive filesystems like windows.
+     */
+    protected boolean isSameFile(FileObject destFile) throws FileSystemException
+    {
+        attach();
+        return doIsSameFile(destFile);
+    }
+
+    /**
+     * Checks if this fileObject is the same file as <code>destFile</code> just with a different
+     * name.<br />
+     * E.g. for case insensitive filesystems like windows.
+     */
+    protected boolean doIsSameFile(FileObject destFile) throws FileSystemException
+    {
+        return false;
+    }
+
+    /**
+     * Queries the object if a simple rename to the filename of <code>newfile</code>
+     * is possible.
+     *
+     * @param newfile the new filename
+     * @return true if rename is possible
+     */
+    public boolean canRenameTo(FileObject newfile)
+    {
+        if (getFileSystem() == newfile.getFileSystem())
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Finds the set of matching descendents of this file, in depthwise
+     * order.
+     *
+     * @param selector The FileSelector.
+     * @return list of files or null if the base file (this object) do not exist
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject[] findFiles(final FileSelector selector) throws FileSystemException
+    {
+        if (!exists())
+        {
+            return null;
+        }
+
+        final ArrayList list = new ArrayList();
+        findFiles(selector, true, list);
+        return (FileObject[]) list.toArray(new FileObject[list.size()]);
+    }
+
+    /**
+     * Returns the file's content.
+     * @return the FileContent for this FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileContent getContent() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            attach();
+            if (content == null)
+            {
+                content = doCreateFileContent();
+            }
+            return content;
+        }
+    }
+
+    /**
+     * Create a FileContent implementation.
+     */
+    protected FileContent doCreateFileContent() throws FileSystemException
+    {
+        return new DefaultFileContent(this, getFileContentInfoFactory());
+    }
+
+    /**
+     * This will prepare the fileObject to get resynchronized with the underlaying filesystem if required.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void refresh() throws FileSystemException
+    {
+        // Detach from the file
+        try
+        {
+            detach();
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/resync.error", name, e);
+        }
+    }
+
+    /**
+     * Closes this file, and its content.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void close() throws FileSystemException
+    {
+        FileSystemException exc = null;
+
+        // Close the content
+        if (content != null)
+        {
+            try
+            {
+                content.close();
+                content = null;
+            }
+            catch (FileSystemException e)
+            {
+                exc = e;
+            }
+        }
+
+        // Detach from the file
+        try
+        {
+            detach();
+        }
+        catch (final Exception e)
+        {
+            exc = new FileSystemException("vfs.provider/close.error", name, e);
+        }
+
+        if (exc != null)
+        {
+            throw exc;
+        }
+    }
+
+    /**
+     * Returns an input stream to use to read the content of the file.
+     * @return The InputStream to access this file's content.
+     * @throws FileSystemException if an error occurs.
+     */
+    public InputStream getInputStream() throws FileSystemException
+    {
+        /* VFS-210
+        if (!getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/read-not-file.error", name);
+        }
+        if (!isReadable())
+        {
+            throw new FileSystemException("vfs.provider/read-not-readable.error", name);
+        }
+        */
+
+        // Get the raw input stream
+        try
+        {
+            return doGetInputStream();
+        }
+        catch (final org.apache.commons.vfs.FileNotFoundException exc)
+        {
+            throw new org.apache.commons.vfs.FileNotFoundException(name, exc);
+        }
+        catch (final FileNotFoundException exc)
+        {
+            throw new org.apache.commons.vfs.FileNotFoundException(name, exc);
+        }
+        catch (final FileSystemException exc)
+        {
+            throw exc;
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/read.error", name, exc);
+        }
+    }
+
+    /**
+     * Returns an input/output stream to use to read and write the content of the file in and
+     * random manner.
+     * @param mode The RandomAccessMode.
+     * @return The RandomAccessContent.
+     * @throws FileSystemException if an error occurs.
+     */
+    public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException
+    {
+        /* VFS-210
+        if (!getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/read-not-file.error", name);
+        }
+        */
+
+        if (mode.requestRead())
+        {
+            if (!getFileSystem().hasCapability(Capability.RANDOM_ACCESS_READ))
+            {
+                throw new FileSystemException("vfs.provider/random-access-read-not-supported.error");
+            }
+            if (!isReadable())
+            {
+                throw new FileSystemException("vfs.provider/read-not-readable.error", name);
+            }
+        }
+
+        if (mode.requestWrite())
+        {
+            if (!getFileSystem().hasCapability(Capability.RANDOM_ACCESS_WRITE))
+            {
+                throw new FileSystemException("vfs.provider/random-access-write-not-supported.error");
+            }
+            if (!isWriteable())
+            {
+                throw new FileSystemException("vfs.provider/write-read-only.error", name);
+            }
+        }
+
+        // Get the raw input stream
+        try
+        {
+            return doGetRandomAccessContent(mode);
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/random-access.error", name, exc);
+        }
+    }
+
+    /**
+     * Prepares this file for writing.  Makes sure it is either a file,
+     * or its parent folder exists.  Returns an output stream to use to
+     * write the content of the file to.
+     * @return An OutputStream where the new contents of the file can be written.
+     * @throws FileSystemException if an error occurs.
+     */
+    public OutputStream getOutputStream() throws FileSystemException
+    {
+        return getOutputStream(false);
+    }
+
+    /**
+     * Prepares this file for writing.  Makes sure it is either a file,
+     * or its parent folder exists.  Returns an output stream to use to
+     * write the content of the file to.<br>
+     *
+     * @param bAppend true when append to the file.<br>
+     *                Note: If the underlaying filesystem do not support this, it wont work.
+     * @return An OutputStream where the new contents of the file can be written.
+     * @throws FileSystemException if an error occurs.
+     */
+    public OutputStream getOutputStream(boolean bAppend) throws FileSystemException
+    {
+        /* VFS-210
+        if (getType() != FileType.IMAGINARY && !getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/write-not-file.error", name);
+        }
+        if (!isWriteable())
+        {
+            throw new FileSystemException("vfs.provider/write-read-only.error", name);
+        }
+        */
+
+        if (bAppend && !getFileSystem().hasCapability(Capability.APPEND_CONTENT))
+        {
+            throw new FileSystemException("vfs.provider/write-append-not-supported.error", name);
+        }
+
+        if (getType() == FileType.IMAGINARY)
+        {
+// Does not exist - make sure parent does
+            FileObject parent = getParent();
+            if (parent != null)
+            {
+                parent.createFolder();
+            }
+        }
+
+// Get the raw output stream
+        try
+        {
+            return doGetOutputStream(bAppend);
+        }
+        catch (RuntimeException re)
+        {
+            throw re;
+        }
+        catch (Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/write.error", new Object[]{name}, exc);
+        }
+    }
+
+    /**
+     * Detaches this file, invaliating all cached info.  This will force
+     * a call to {@link #doAttach} next time this file is used.
+     */
+    private void detach() throws Exception
+    {
+        synchronized (fs)
+        {
+            if (attached)
+            {
+                try
+                {
+                    doDetach();
+                }
+                finally
+                {
+                    attached = false;
+                    setFileType(null);
+                    parent = null;
+
+                    // fs.fileDetached(this);
+
+                    removeChildrenCache();
+                    // children = null;
+                }
+            }
+        }
+    }
+
+    private void removeChildrenCache()
+    {
+        /*
+        if (children != null)
+        {
+            for (int iterChildren = 0; iterChildren < children.length; iterChildren++)
+            {
+                fs.removeFileFromCache(children[iterChildren].getName());
+            }
+
+            children = null;
+        }
+        */
+        children = null;
+    }
+
+    /**
+     * Attaches to the file.
+     */
+    private void attach() throws FileSystemException
+    {
+        synchronized (fs)
+        {
+            if (attached)
+            {
+                return;
+            }
+
+            try
+            {
+                // Attach and determine the file type
+                doAttach();
+                attached = true;
+                // now the type could already be injected by doAttach (e.g from parent to child)
+
+                /* VFS-210: determine the type when really asked fore
+                if (type == null)
+                {
+                    setFileType(doGetType());
+                }
+                if (type == null)
+                {
+                    setFileType(FileType.IMAGINARY);
+                }
+                */
+            }
+            catch (Exception exc)
+            {
+                throw new FileSystemException("vfs.provider/get-type.error", new Object[]{name}, exc);
+            }
+
+            // fs.fileAttached(this);
+        }
+    }
+
+    /**
+     * Called when the ouput stream for this file is closed.
+     */
+    protected void endOutput() throws Exception
+    {
+        if (getType() == FileType.IMAGINARY)
+        {
+            // File was created
+            handleCreate(FileType.FILE);
+        }
+        else
+        {
+            // File has changed
+            onChange();
+        }
+    }
+
+    /**
+     * Called when this file is created.  Updates cached info and notifies
+     * the parent and file system.
+     */
+    protected void handleCreate(final FileType newType) throws Exception
+    {
+        synchronized (fs)
+        {
+            if (attached)
+            {
+                // Fix up state
+                injectType(newType);
+
+                removeChildrenCache();
+                // children = EMPTY_FILE_ARRAY;
+
+                // Notify subclass
+                onChange();
+            }
+
+            // Notify parent that its child list may no longer be valid
+            notifyParent(this.getName(), newType);
+
+            // Notify the file system
+            fs.fireFileCreated(this);
+        }
+    }
+
+    /**
+     * Called when this file is deleted.  Updates cached info and notifies
+     * subclasses, parent and file system.
+     */
+    protected void handleDelete() throws Exception
+    {
+        synchronized (fs)
+        {
+            if (attached)
+            {
+                // Fix up state
+                injectType(FileType.IMAGINARY);
+                removeChildrenCache();
+                // children = null;
+
+                // Notify subclass
+                onChange();
+            }
+
+            // Notify parent that its child list may no longer be valid
+            notifyParent(this.getName(), FileType.IMAGINARY);
+
+            // Notify the file system
+            fs.fireFileDeleted(this);
+        }
+    }
+
+    /**
+     * Called when this file is changed.<br />
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
+     */
+    protected void handleChanged() throws Exception
+    {
+        // Notify the file system
+        fs.fireFileChanged(this);
+    }
+
+    /**
+     * Notifies the file that its children have changed.
+     *
+     * @deprecated use {@link #childrenChanged(FileName,FileType)}
+     */
+    protected void childrenChanged() throws Exception
+    {
+        childrenChanged(null, null);
+    }
+
+    /**
+     * Notifies the file that its children have changed.
+     */
+    protected void childrenChanged(FileName childName, FileType newType) throws Exception
+    {
+        // TODO - this may be called when not attached
+
+        if (children != null)
+        {
+            if (childName != null && newType != null)
+            {
+                // TODO - figure out if children[] can be replaced by list
+                ArrayList list = new ArrayList(Arrays.asList(children));
+                if (newType.equals(FileType.IMAGINARY))
+                {
+                    list.remove(childName);
+                }
+                else
+                {
+                    list.add(childName);
+                }
+                children = new FileName[list.size()];
+                list.toArray(children);
+            }
+        }
+
+        // removeChildrenCache();
+        onChildrenChanged(childName, newType);
+    }
+
+    /**
+     * Notify the parent of a change to its children, when a child is created
+     * or deleted.
+     */
+    private void notifyParent(FileName childName, FileType newType) throws Exception
+    {
+        if (parent == null)
+        {
+            FileName parentName = name.getParent();
+            if (parentName != null)
+            {
+                // Locate the parent, if it is cached
+                parent = fs.getFileFromCache(parentName);
+            }
+        }
+
+        if (parent != null)
+        {
+            FileObjectUtils.getAbstractFileObject(parent).childrenChanged(childName, newType);
+        }
+    }
+
+    /**
+     * Traverses the descendents of this file, and builds a list of selected
+     * files.
+     * @param selector The FileSelector.
+     * @param depthwise if true files are added after their descendants, before otherwise.
+     * @param selected A List of the located FileObjects.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void findFiles(final FileSelector selector,
+                          final boolean depthwise,
+                          final List selected) throws FileSystemException
+    {
+        try
+        {
+            if (exists())
+            {
+                // Traverse starting at this file
+                final DefaultFileSelectorInfo info = new DefaultFileSelectorInfo();
+                info.setBaseFolder(this);
+                info.setDepth(0);
+                info.setFile(this);
+                traverse(info, selector, depthwise, selected);
+            }
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/find-files.error", name, e);
+        }
+    }
+
+    /**
+     * Traverses a file.
+     */
+    private static void traverse(final DefaultFileSelectorInfo fileInfo,
+                                 final FileSelector selector,
+                                 final boolean depthwise,
+                                 final List selected)
+        throws Exception
+    {
+        // Check the file itself
+        final FileObject file = fileInfo.getFile();
+        final int index = selected.size();
+
+        // If the file is a folder, traverse it
+        if (file.getType().hasChildren() && selector.traverseDescendents(fileInfo))
+        {
+            final int curDepth = fileInfo.getDepth();
+            fileInfo.setDepth(curDepth + 1);
+
+            // Traverse the children
+            final FileObject[] children = file.getChildren();
+            for (int i = 0; i < children.length; i++)
+            {
+                final FileObject child = children[i];
+                fileInfo.setFile(child);
+                traverse(fileInfo, selector, depthwise, selected);
+            }
+
+            fileInfo.setFile(file);
+            fileInfo.setDepth(curDepth);
+        }
+
+        // Add the file if doing depthwise traversal
+        if (selector.includeFile(fileInfo))
+        {
+            if (depthwise)
+            {
+                // Add this file after its descendents
+                selected.add(file);
+            }
+            else
+            {
+                // Add this file before its descendents
+                selected.add(index, file);
+            }
+        }
+    }
+
+    /**
+     * Check if the content stream is open.
+     *
+     * @return true if this is the case
+     */
+    public boolean isContentOpen()
+    {
+        if (content == null)
+        {
+            return false;
+        }
+
+        return content.isOpen();
+    }
+
+    /**
+     * Check if the internal state is "attached".
+     *
+     * @return true if this is the case
+     */
+    public boolean isAttached()
+    {
+        return attached;
+    }
+
+    /**
+     * create the filecontentinfo implementation
+     */
+    protected FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return getFileSystem().getFileSystemManager().getFileContentInfoFactory();
+    }
+
+    protected void injectType(FileType fileType)
+    {
+        setFileType(fileType);
+    }
+
+    private void setFileType(FileType type)
+    {
+        if (type != null && type != FileType.IMAGINARY)
+        {
+            try
+            {
+                name.setType(type);
+            }
+            catch (FileSystemException e)
+            {
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+        this.type = type;
+    }
+
+    /**
+     * This method is meant to add an object where this object holds a strong reference then.
+     * E.g. a archive-filesystem creates a list of all childs and they shouldnt get
+     * garbage collected until the container is garbage collected
+     *
+     * @param strongRef The Object to add.
+     */
+    public void holdObject(Object strongRef)
+    {
+        if (objects == null)
+        {
+            objects = new ArrayList(INITIAL_LISTSZ);
+        }
+        objects.add(strongRef);
+    }
+
+    /**
+     * will be called after this file-object closed all its streams.
+     */
+    protected void notifyAllStreamsClosed()
+    {
+    }
+
+    // --- OPERATIONS ---
+
+    /**
+     * @return FileOperations interface that provides access to the operations
+     *         API.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileOperations getFileOperations() throws FileSystemException
+    {
+        if (operations == null)
+        {
+            operations = new DefaultFileOperations(this);
+        }
+
+        return operations;
+    }
+
+    protected void finalize() throws Throwable
+    {
+        fs.fileObjectDestroyed(this);
+
+        super.finalize();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileProvider.java
new file mode 100644
index 0000000..a801259
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileProvider.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.local.GenericFileNameParser;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * A partial {@link FileProvider} implementation.  Takes care of managing the
+ * file systems created by the provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractFileProvider
+    extends AbstractVfsContainer
+    implements FileProvider
+{
+    /**
+     * The cached file systems.  This is a mapping from root URI to
+     * FileSystem object.
+     */
+    // private final Map fileSystems = new HashMap();
+    private final Map fileSystems = new TreeMap();
+
+    private FileNameParser parser;
+
+    public AbstractFileProvider()
+    {
+        parser = GenericFileNameParser.getInstance();
+    }
+
+    protected FileNameParser getFileNameParser()
+    {
+        return parser;
+    }
+
+    protected void setFileNameParser(FileNameParser parser)
+    {
+        this.parser = parser;
+    }
+
+    /**
+     * Closes the file systems created by this provider.
+     */
+    public void close()
+    {
+        synchronized (this)
+        {
+            fileSystems.clear();
+        }
+
+        super.close();
+    }
+
+    /**
+     * Creates a layered file system.  This method throws a 'not supported' exception.
+     * @param scheme The protocol to use to access the file.
+     * @param file a FileObject.
+     * @param properties Options to the file system.
+     * @return A FileObject associated with the new FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final String scheme, final FileObject file, final FileSystemOptions properties)
+        throws FileSystemException
+    {
+        // Can't create a layered file system
+        throw new FileSystemException("vfs.provider/not-layered-fs.error", scheme);
+    }
+
+    /**
+     * Adds a file system to those cached by this provider.  The file system
+     * may implement {@link VfsComponent}, in which case it is initialised.
+     */
+    protected void addFileSystem(final Comparable key, final FileSystem fs)
+        throws FileSystemException
+    {
+        // Add to the cache
+        addComponent(fs);
+
+        FileSystemKey treeKey = new FileSystemKey(key, fs.getFileSystemOptions());
+        ((AbstractFileSystem) fs).setCacheKey(treeKey);
+
+        synchronized (this)
+        {
+            fileSystems.put(treeKey, fs);
+        }
+    }
+
+    /**
+     * Locates a cached file system
+     *
+     * @return The provider, or null if it is not cached.
+     */
+    protected FileSystem findFileSystem(final Comparable key, final FileSystemOptions fileSystemProps)
+    {
+        FileSystemKey treeKey = new FileSystemKey(key, fileSystemProps);
+
+        synchronized (this)
+        {
+            return (FileSystem) fileSystems.get(treeKey);
+        }
+    }
+
+    /**
+     * Returns the FileSystemConfigBuidler.
+     * @return the FileSystemConfigBuilder.
+     */
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return null;
+    }
+
+    /**
+     * Free unused resources.
+     */
+    public void freeUnusedResources()
+    {
+        Object[] item;
+        synchronized (this)
+        {
+            item = fileSystems.values().toArray();
+        }
+        for (int i = 0; i < item.length; ++i)
+        {
+            AbstractFileSystem fs = (AbstractFileSystem) item[i];
+            if (fs.isReleaseable())
+            {
+                fs.closeCommunicationLink();
+            }
+        }
+    }
+
+    /**
+     * Close the FileSystem.
+     * @param filesystem The FileSystem to close.
+     */
+    public void closeFileSystem(final FileSystem filesystem)
+    {
+        AbstractFileSystem fs = (AbstractFileSystem) filesystem;
+
+        synchronized (this)
+        {
+            if (fs.getCacheKey() != null)
+            {
+                fileSystems.remove(fs.getCacheKey());
+            }
+        }
+
+        removeComponent(fs);
+        fs.close();
+    }
+
+    /**
+     * Parses an absolute URI.
+     *
+     * @param base The base file - if null the <code>uri</code> needs to be absolute
+     * @param uri The URI to parse.
+     * @return The FileName.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName parseUri(FileName base, String uri) throws FileSystemException
+    {
+        if (getFileNameParser() != null)
+        {
+            return getFileNameParser().parseUri(getContext(), base, uri);
+        }
+
+        throw new FileSystemException("vfs.provider/filename-parser-missing.error");
+        // return GenericFileName.parseUri(getFileNameParser(), uri, 0);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileSystem.java
new file mode 100644
index 0000000..75b9f58
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractFileSystem.java
@@ -0,0 +1,686 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.CacheStrategy;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
+import org.apache.commons.vfs.cache.OnCallRefreshFileObject;
+import org.apache.commons.vfs.events.AbstractFileChangeEvent;
+import org.apache.commons.vfs.events.ChangedEvent;
+import org.apache.commons.vfs.events.CreateEvent;
+import org.apache.commons.vfs.events.DeleteEvent;
+import org.apache.commons.vfs.util.Messages;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * A partial {@link org.apache.commons.vfs.FileSystem} implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractFileSystem
+    extends AbstractVfsComponent
+    implements FileSystem
+{
+    private static final Log LOG = LogFactory.getLog(AbstractFileSystem.class);
+
+    /**
+     * The "root" of the file system. This is always "/" so it isn't always the "real"
+     * root.
+     */
+    private final FileName rootName;
+
+    /**
+     * The root URI of the file system. The base path specified as a file system option
+     * when the file system was created.
+     */
+    private final String rootURI;
+
+    private FileObject parentLayer;
+    // private FileObject root;
+    private final Collection caps = new HashSet();
+
+    /**
+     * Map from FileName to FileObject.
+     */
+    // private FilesCache files;
+
+    /**
+     * Map from FileName to an ArrayList of listeners for that file.
+     */
+    private final Map listenerMap = new HashMap();
+
+    /**
+     * FileSystemOptions used for configuration
+     */
+    private final FileSystemOptions fileSystemOptions;
+
+    /**
+     * How many fileObjects are handed out
+     */
+    private long useCount;
+
+
+    private FileSystemKey cacheKey;
+
+    /**
+     * open streams counter for this filesystem
+     */
+    private int openStreams;
+
+    protected AbstractFileSystem(final FileName rootName,
+                                 final FileObject parentLayer,
+                                 final FileSystemOptions fileSystemOptions)
+    {
+        // this.parentLayer = parentLayer;
+        this.parentLayer = parentLayer;
+        this.rootName = rootName;
+        this.fileSystemOptions = fileSystemOptions;
+        FileSystemConfigBuilder builder = DefaultFileSystemConfigBuilder.getInstance();
+        String uri = builder.getRootURI(fileSystemOptions);
+        if (uri == null)
+        {
+            uri = rootName.getURI();
+        }
+        this.rootURI = uri;
+    }
+
+    /**
+     * Initialises this component.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+        addCapabilities(caps);
+    }
+
+    /**
+     * Closes this component.
+     */
+    public void close()
+    {
+        closeCommunicationLink();
+
+        parentLayer = null;
+    }
+
+    /**
+     * Close the underlaying link used to access the files.
+     */
+    public void closeCommunicationLink()
+    {
+        synchronized (this)
+        {
+            doCloseCommunicationLink();
+        }
+    }
+
+    /**
+     * Close the underlaying link used to access the files
+     */
+    protected void doCloseCommunicationLink()
+    {
+    }
+
+    /**
+     * Creates a file object.  This method is called only if the requested
+     * file is not cached.
+     */
+    protected abstract FileObject createFile(final FileName name)
+        throws Exception;
+
+    /**
+     * Adds the capabilities of this file system.
+     */
+    protected abstract void addCapabilities(Collection caps);
+
+    /**
+     * Returns the name of the root of this file system.
+     * @return the root FileName.
+     */
+    public FileName getRootName()
+    {
+        return rootName;
+    }
+
+    /**
+     * Returns the root URI specified for this file System.
+     * @return The root URI used in this file system.
+     */
+    public String getRootURI()
+    {
+        return rootURI;
+    }
+
+    /**
+     * Adds a file object to the cache.
+     */
+    protected void putFileToCache(final FileObject file)
+    {
+        getCache().putFile(file);
+        // files.put(file.getName(), file);
+    }
+
+    private FilesCache getCache()
+    {
+        FilesCache files;
+        //if (this.files == null)
+        //{
+            files = getContext().getFileSystemManager().getFilesCache();
+            if (files == null)
+            {
+                throw new RuntimeException(Messages.getString("vfs.provider/files-cache-missing.error"));
+            }
+        //}
+
+        return files;
+    }
+
+    /**
+     * Returns a cached file.
+     */
+    protected FileObject getFileFromCache(final FileName name)
+    {
+        return getCache().getFile(this, name);
+        // return (FileObject) files.get(name);
+    }
+
+    /**
+     * remove a cached file.
+     */
+    protected void removeFileFromCache(final FileName name)
+    {
+        getCache().removeFile(this, name);
+    }
+
+    /**
+     * 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.
+     */
+    public boolean hasCapability(final Capability capability)
+    {
+        return caps.contains(capability);
+    }
+
+    /**
+     * 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.
+     */
+    public Object getAttribute(final String attrName) throws FileSystemException
+    {
+        throw new FileSystemException("vfs.provider/get-attribute-not-supported.error");
+    }
+
+    /**
+     * 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.
+     */
+    public void setAttribute(final String attrName, final Object value)
+        throws FileSystemException
+    {
+        throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
+    }
+
+    /**
+     * Returns the parent layer if this is a layered file system.
+     * @return The FileObject for the parent layer.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getParentLayer() throws FileSystemException
+    {
+        return parentLayer;
+    }
+
+    /**
+     * Returns the root file of this file system.
+     * @return The root FileObject of the FileSystem
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getRoot() throws FileSystemException
+    {
+        return resolveFile(rootName);
+        /*
+        if (root == null)
+        {
+            root = resolveFile(rootName);
+        }
+        return root;
+        */
+    }
+
+    /**
+     * 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.
+     */
+    public FileObject resolveFile(final String nameStr) throws FileSystemException
+    {
+        // Resolve the name, and create the file
+        final FileName name = getFileSystemManager().resolveName(rootName, nameStr);
+        return resolveFile(name);
+    }
+
+    /**
+     * Finds a file in 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.
+     */
+    public synchronized FileObject resolveFile(final FileName name) throws FileSystemException
+    {
+        return resolveFile(name, true);
+    }
+
+    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",
+                new Object[]{
+                    name, rootName, name.getRootURI()});
+        }
+
+        // imario@apache.org ==> use getFileFromCache
+        FileObject file;
+        if (useCache)
+        {
+            file = getFileFromCache(name);
+        }
+        else
+        {
+            file = null;
+        }
+        // FileObject file = (FileObject) files.get(name);
+        if (file == null)
+        {
+            try
+            {
+                synchronized (this)
+                {
+                    file = createFile(name);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new FileSystemException("vfs.provider/resolve-file.error", name, e);
+            }
+
+            file = decorateFileObject(file);
+
+            // imario@apache.org ==> use putFileToCache
+            if (useCache)
+            {
+                putFileToCache(file);
+            }
+            // files.put(name, 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(new Object[]{file});
+            }
+            catch (InstantiationException e)
+            {
+                throw new FileSystemException("vfs.impl/invalid-decorator.error",
+                        getFileSystemManager().getFileObjectDecorator().getName(), e);
+            }
+            catch (IllegalAccessException e)
+            {
+                throw new FileSystemException("vfs.impl/invalid-decorator.error",
+                        getFileSystemManager().getFileObjectDecorator().getName(), e);
+            }
+            catch (InvocationTargetException e)
+            {
+                throw new FileSystemException("vfs.impl/invalid-decorator.error",
+                        getFileSystemManager().getFileObjectDecorator().getName(), e);
+            }
+        }
+
+        return file;
+    }
+
+    /**
+     * Creates a temporary local copy of a file and its descendents.
+     * @param file The FileObject to replicate.
+     * @param selector The FileSelector.
+     * @return The replicated File.
+     * @throws FileSystemException if an error occurs.
+     */
+    public File replicateFile(final FileObject file,
+                              final FileSelector selector)
+        throws FileSystemException
+    {
+        if (!file.exists())
+        {
+            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);
+        }
+    }
+
+    /**
+     * Return the FileSystemOptions used to instantiate this filesystem.
+     * @return the FileSystemOptions.
+     */
+    public FileSystemOptions getFileSystemOptions()
+    {
+        return fileSystemOptions;
+    }
+
+    /**
+     * Return the FileSystemManager used to instantiate this filesystem.
+     * @return the FileSystemManager.
+     */
+    public FileSystemManager getFileSystemManager()
+    {
+        return getContext().getFileSystemManager();
+        // return manager;
+    }
+
+    /**
+     * Returns the accuracy of the last modification time.
+     *
+     * @return ms 0 perfectly accurate, >0 might be off by this value e.g. sftp 1000ms
+     */
+    public double getLastModTimeAccuracy()
+    {
+        return 0;
+    }
+
+    /**
+     * Creates a temporary local copy of a file and its descendents.
+     */
+    protected File doReplicateFile(final FileObject file,
+                                   final FileSelector selector)
+        throws Exception
+    {
+        return getContext().getReplicator().replicateFile(file, selector);
+    }
+
+    /**
+     * Adds a junction to this file system.
+     * @param junctionPoint The junction point.
+     * @param targetFile The target to add.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void addJunction(final String junctionPoint,
+                            final FileObject targetFile)
+        throws FileSystemException
+    {
+        throw new FileSystemException("vfs.provider/junctions-not-supported.error", rootName);
+    }
+
+    /**
+     * Removes a junction from this file system.
+     * @param junctionPoint The junction point.
+     * @throws FileSystemException if an error occurs
+     */
+    public void removeJunction(final String junctionPoint) 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
+     */
+    public void addListener(final FileObject file,
+                            final FileListener listener)
+    {
+        synchronized (listenerMap)
+        {
+            ArrayList listeners = (ArrayList) listenerMap.get(file.getName());
+            if (listeners == null)
+            {
+                listeners = new ArrayList();
+                listenerMap.put(file.getName(), listeners);
+            }
+            listeners.add(listener);
+        }
+    }
+
+    /**
+     * Removes a listener from a file in this file system.
+     * @param file The FileObject to be monitored.
+     * @param listener The FileListener
+     */
+    public void removeListener(final FileObject file,
+                               final FileListener listener)
+    {
+        synchronized (listenerMap)
+        {
+            final ArrayList listeners = (ArrayList) listenerMap.get(file.getName());
+            if (listeners != null)
+            {
+                listeners.remove(listener);
+                if (listeners.isEmpty())
+                {
+                    listenerMap.remove(file.getName());
+                }
+            }
+        }
+    }
+
+    /**
+     * Fires a file create event.
+     * @param file The FileObject that was created.
+     */
+    public void fireFileCreated(final FileObject file)
+    {
+        fireEvent(new CreateEvent(file));
+    }
+
+    /**
+     * Fires a file delete event.
+     * @param file The FileObject that was deleted.
+     */
+    public void fireFileDeleted(final FileObject file)
+    {
+        fireEvent(new DeleteEvent(file));
+    }
+
+    /**
+     * Fires a file changed event. <br />
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
+     * @param file The FileObject that changed.
+     */
+    public void fireFileChanged(final FileObject file)
+    {
+        fireEvent(new ChangedEvent(file));
+    }
+
+    /**
+     * returns true if no file is using this filesystem.
+     * @return true of no file is using this FileSystem.
+     */
+    public boolean isReleaseable()
+    {
+        return useCount < 1;
+    }
+
+    void freeResources()
+    {
+    }
+
+    /**
+     * Fires an event.
+     */
+    private void fireEvent(final AbstractFileChangeEvent event)
+    {
+        FileListener[] fileListeners = null;
+        final FileObject file = event.getFile();
+
+        synchronized (listenerMap)
+        {
+            final ArrayList listeners = (ArrayList) listenerMap.get(file.getName());
+            if (listeners != null)
+            {
+                fileListeners = (FileListener[]) listeners.toArray(new FileListener[listeners.size()]);
+            }
+        }
+
+        if (fileListeners != null)
+        {
+            for (int i = 0; i < fileListeners.length; i++)
+            {
+                final FileListener fileListener = fileListeners[i];
+                try
+                {
+                    event.notify(fileListener);
+                }
+                catch (final Exception e)
+                {
+                    final String message = Messages.getString("vfs.provider/notify-listener.warn", file);
+                    // getLogger().warn(message, e);
+                    VfsLog.warn(getLogger(), LOG, message, e);
+                }
+            }
+        }
+    }
+
+    /*
+    void fileDetached(FileObject fileObject)
+    {
+        useCount--;
+    }
+
+    void fileAttached(FileObject fileObject)
+    {
+        useCount++;
+
+    }
+    */
+
+    void fileObjectHanded(FileObject fileObject)
+    {
+        useCount++;
+    }
+
+    void fileObjectDestroyed(FileObject fileObject)
+    {
+        useCount--;
+    }
+
+    void setCacheKey(FileSystemKey cacheKey)
+    {
+        this.cacheKey = cacheKey;
+    }
+
+    FileSystemKey getCacheKey()
+    {
+        return this.cacheKey;
+    }
+
+    void streamOpened()
+    {
+        synchronized (this)
+        {
+            openStreams++;
+        }
+    }
+
+    void streamClosed()
+    {
+        synchronized (this)
+        {
+            if (openStreams > 0)
+            {
+                openStreams--;
+                if (openStreams < 1)
+                {
+                    notifyAllStreamsClosed();
+                }
+            }
+        }
+    }
+
+    /**
+     * will be called after all file-objects closed their streams.
+     */
+    protected void notifyAllStreamsClosed()
+    {
+    }
+
+    /**
+     * check if this filesystem has open streams.
+     * @return true if the FileSystem has open streams.
+     */
+    public boolean isOpen()
+    {
+        synchronized (this)
+        {
+            return openStreams > 0;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractLayeredFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractLayeredFileProvider.java
new file mode 100644
index 0000000..3d1664f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractLayeredFileProvider.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * A {@link FileProvider} that is layered on top of another, such as the
+ * contents of a zip or tar file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractLayeredFileProvider
+    extends AbstractFileProvider
+    implements FileProvider
+{
+    public AbstractLayeredFileProvider()
+    {
+        super();
+        setFileNameParser(LayeredFileNameParser.getInstance());
+    }
+
+    /**
+     * Locates a file object, by absolute URI.
+     * @param baseFile The base FileObject.
+     * @param uri The name of the file to locate.
+     * @param properties The FileSystemOptions.
+     * @return The FileObject if it is located, null otherwise.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject findFile(final FileObject baseFile,
+                               final String uri,
+                               final FileSystemOptions properties) 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(), properties);
+
+        // Create the file system
+        final FileObject rootFile = createFileSystem(name.getScheme(), file, properties);
+
+        // Resolve the file
+        return rootFile.resolveFile(name.getPath());
+    }
+
+    /**
+     * Creates a layered file system.
+     * @param scheme The protocol to use.
+     * @param file a FileObject.
+     * @param fileSystemOptions Options to access the FileSystem.
+     * @return A FileObject associated with the new FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public synchronized FileObject createFileSystem(final String scheme,
+                                                    final FileObject file,
+                                                    final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Check if cached
+        final FileName rootName = file.getName();
+        FileSystem fs = findFileSystem(rootName, null);
+        if (fs == null)
+        {
+            // Create the file system
+            fs = doCreateFileSystem(scheme, file, fileSystemOptions);
+            addFileSystem(rootName, fs);
+        }
+        return fs.getRoot();
+    }
+
+    /**
+     * Creates a layered file system.  This method is called if the file system
+     * is not cached.  The file system may implement {@link VfsComponent}.
+     *
+     * @param scheme The URI scheme.
+     * @param file   The file to create the file system on top of.
+     * @return The file system.
+     */
+    protected abstract FileSystem doCreateFileSystem(final String scheme,
+                                                     final FileObject file,
+                                                     final FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractOriginatingFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractOriginatingFileProvider.java
new file mode 100644
index 0000000..60d046b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractOriginatingFileProvider.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * A {@link FileProvider} that handles physical files, such as the files in a
+ * local fs, or on an FTP server.  An originating file system cannot be
+ * layered on top of another file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractOriginatingFileProvider
+    extends AbstractFileProvider
+{
+    public AbstractOriginatingFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Locates a file object, by absolute URI.
+     *
+     * @param baseFile 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.
+     */
+    public FileObject findFile(final FileObject baseFile,
+                               final String uri,
+                               final FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        // Parse the URI
+        final FileName name;
+        try
+        {
+            name = parseUri(baseFile != null ? baseFile.getName() : null, uri);
+        }
+        catch (FileSystemException exc)
+        {
+            throw new FileSystemException("vfs.provider/invalid-absolute-uri.error", uri, exc);
+        }
+
+        // Locate the file
+        return findFile(name, fileSystemOptions);
+    }
+
+    /**
+     * Locates a file from its parsed URI.
+     * @param name The file name.
+     * @param fileSystemOptions FileSystem options.
+     * @return A FileObject associated with the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    protected FileObject findFile(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Check in the cache for the file system
+        final FileName rootName = getContext().getFileSystemManager().resolveName(name, FileName.ROOT_PATH);
+
+        FileSystem fs = getFileSystem(rootName, fileSystemOptions);
+
+        // Locate the file
+        // return fs.resolveFile(name.getPath());
+        return fs.resolveFile(name);
+    }
+
+    /**
+     * Returns the FileSystem associated with the specified root.
+     * @param rootName The root path.
+     * @param fileSystemOptions The FileSystem options.
+     * @return The FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    protected synchronized FileSystem getFileSystem(FileName rootName, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        FileSystem fs = findFileSystem(rootName, fileSystemOptions);
+        if (fs == null)
+        {
+            // Need to create the file system, and cache it
+            fs = doCreateFileSystem(rootName, fileSystemOptions);
+            addFileSystem(rootName, fs);
+        }
+        return fs;
+    }
+
+
+
+    /**
+     * Creates a {@link FileSystem}.  If the returned FileSystem implements
+     * {@link VfsComponent}, it will be initialised.
+     *
+     * @param rootName 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(final FileName rootName, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessContent.java
new file mode 100644
index 0000000..f14e2a1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessContent.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.IOException;
+
+/**
+ * Implements the DataOutput part of the RandomAccessContent interface and throws
+ * UnsupportedOperationException if one of those methods are called.
+ * (for read-only random access implementations)
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractRandomAccessContent implements RandomAccessContent
+{
+    private final RandomAccessMode mode;
+
+    protected AbstractRandomAccessContent(final RandomAccessMode mode)
+    {
+        this.mode = mode;
+    }
+
+    public void writeDouble(double v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeFloat(float v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void write(int b) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeByte(int v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeChar(int v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeInt(int v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeShort(int v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeLong(long v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeBoolean(boolean v) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void write(byte[] b) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeBytes(String s) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeChars(String s) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void writeUTF(String str) throws IOException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @deprecated see {@link java.io.DataInputStream#readLine()}
+     * @return The line as a String.
+     * @throws IOException if an error occurs.
+     */
+    public String readLine() throws IOException
+    {
+        throw new UnsupportedOperationException("deprecated");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessStreamContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessStreamContent.java
new file mode 100644
index 0000000..27a12d7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractRandomAccessStreamContent.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * Implements the part usable for all stream base random access implementations.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractRandomAccessStreamContent extends AbstractRandomAccessContent
+{
+    protected AbstractRandomAccessStreamContent(final RandomAccessMode mode)
+    {
+        super(mode);
+    }
+
+    protected abstract DataInputStream getDataInputStream() throws IOException;
+
+    public byte readByte() throws IOException
+    {
+        byte data = getDataInputStream().readByte();
+        return data;
+    }
+
+    public char readChar() throws IOException
+    {
+        char data = getDataInputStream().readChar();
+        return data;
+    }
+
+    public double readDouble() throws IOException
+    {
+        double data = getDataInputStream().readDouble();
+        return data;
+    }
+
+    public float readFloat() throws IOException
+    {
+        float data = getDataInputStream().readFloat();
+        return data;
+    }
+
+    public int readInt() throws IOException
+    {
+        int data = getDataInputStream().readInt();
+        return data;
+    }
+
+    public int readUnsignedByte() throws IOException
+    {
+        int data = getDataInputStream().readUnsignedByte();
+        return data;
+    }
+
+    public int readUnsignedShort() throws IOException
+    {
+        int data = getDataInputStream().readUnsignedShort();
+        return data;
+    }
+
+    public long readLong() throws IOException
+    {
+        long data = getDataInputStream().readLong();
+        return data;
+    }
+
+    public short readShort() throws IOException
+    {
+        short data = getDataInputStream().readShort();
+        return data;
+    }
+
+    public boolean readBoolean() throws IOException
+    {
+        boolean data = getDataInputStream().readBoolean();
+        return data;
+    }
+
+    public int skipBytes(int n) throws IOException
+    {
+        int data = getDataInputStream().skipBytes(n);
+        return data;
+    }
+
+    public void readFully(byte[] b) throws IOException
+    {
+        getDataInputStream().readFully(b);
+    }
+
+    public void readFully(byte[] b, int off, int len) throws IOException
+    {
+        getDataInputStream().readFully(b, off, len);
+    }
+
+    public String readUTF() throws IOException
+    {
+        String data = getDataInputStream().readUTF();
+        return data;
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return getDataInputStream();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsComponent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsComponent.java
new file mode 100644
index 0000000..c89ac3a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsComponent.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * A partial {@link VfsComponent} implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractVfsComponent
+    implements VfsComponent
+{
+    private VfsComponentContext context;
+    private Log log;
+
+    /**
+     * Sets the Logger to use for the component.
+     * @param log The Log to use.
+     */
+    public final void setLogger(final Log log)
+    {
+        this.log = log;
+    }
+
+    /**
+     * Sets the context for this file system provider.
+     * @param context The VfsComponentContext.
+     */
+    public final void setContext(final VfsComponentContext context)
+    {
+        this.context = context;
+    }
+
+    /**
+     * Initialises the component.  This implementation does nothing.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+    }
+
+    /**
+     * Closes the provider.  This implementation does nothing.
+     */
+    public void close()
+    {
+    }
+
+    /**
+     * Returns the logger for this file system to use.
+     */
+    protected final Log getLogger()
+    {
+        return log;
+    }
+
+    /**
+     * Returns the context for this provider.
+     */
+    protected final VfsComponentContext getContext()
+    {
+        return context;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsContainer.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsContainer.java
new file mode 100644
index 0000000..781784f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/AbstractVfsContainer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileSystemException;
+
+import java.util.ArrayList;
+
+/**
+ * A {@link VfsComponent} that contains a set of sub-components.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractVfsContainer
+    extends AbstractVfsComponent
+{
+    /**
+     * The components contained by this component.
+     */
+    private final ArrayList components = new ArrayList();
+
+    /**
+     * Adds a sub-component to this component.  If the sub-component implements
+     * {@link VfsComponent}, it is initialised.  All sub-components are closed
+     * when this component is closed.
+     */
+    protected void addComponent(final Object component)
+        throws FileSystemException
+    {
+        if (!components.contains(component))
+        {
+            // Initialise
+            if (component instanceof VfsComponent)
+            {
+                VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.setLogger(getLogger());
+                vfsComponent.setContext(getContext());
+                vfsComponent.init();
+            }
+
+            // Keep track of component, to close it later
+            components.add(component);
+        }
+    }
+
+    /**
+     * Removes a sub-component from this component.
+     */
+    protected void removeComponent(final Object component)
+    {
+        components.remove(component);
+    }
+
+    /**
+     * Closes the sub-components of this component.
+     */
+    public void close()
+    {
+        // Close all components
+        final int count = components.size();
+        for (int i = 0; i < count; i++)
+        {
+            final Object component = components.get(i);
+            if (component instanceof VfsComponent)
+            {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.close();
+            }
+        }
+        components.clear();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/CompositeFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/CompositeFileProvider.java
new file mode 100644
index 0000000..794495d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/CompositeFileProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * Description.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class CompositeFileProvider extends AbstractFileProvider
+{
+    private static final int INITIAL_BUFSZ = 80;
+
+    public CompositeFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * The schemes to use for resolve
+     */
+    protected abstract String[] getSchemes();
+
+    /**
+     * Locates a file object, by absolute URI.
+     * @param baseFile The base FileObject.
+     * @param uri The file to find.
+     * @param fileSystemOptions The options for the FileSystem.
+     * @return A FileObject for the located file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject findFile(final FileObject baseFile,
+                               final String uri,
+                               final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        StringBuffer buf = new StringBuffer(INITIAL_BUFSZ);
+
+        UriParser.extractScheme(uri, buf);
+
+        String[] schemes = getSchemes();
+        for (int iterSchemes = 0; iterSchemes < schemes.length; iterSchemes++)
+        {
+            buf.insert(0, ":");
+            buf.insert(0, schemes[iterSchemes]);
+        }
+
+        FileObject fo = getContext().getFileSystemManager().resolveFile(buf.toString(), fileSystemOptions);
+        return fo;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileContent.java
new file mode 100644
index 0000000..68afbd1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileContent.java
@@ -0,0 +1,727 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.util.MonitorInputStream;
+import org.apache.commons.vfs.util.MonitorOutputStream;
+import org.apache.commons.vfs.util.MonitorRandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The content of a file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class DefaultFileContent implements FileContent
+{
+    /*
+    static final int STATE_NONE = 0;
+    static final int STATE_READING = 1;
+    static final int STATE_WRITING = 2;
+    static final int STATE_RANDOM_ACCESS = 3;
+    */
+
+    static final int STATE_CLOSED = 0;
+    static final int STATE_OPENED = 1;
+
+    private final AbstractFileObject file;
+    private Map attrs;
+    private Map roAttrs;
+    private FileContentInfo fileContentInfo;
+    private final FileContentInfoFactory fileContentInfoFactory;
+
+    private final ThreadLocal threadData = new ThreadLocal();
+    private boolean resetAttributes;
+
+    /**
+     * open streams counter for this file
+     */
+    private int openStreams;
+
+    public DefaultFileContent(final AbstractFileObject file, final FileContentInfoFactory fileContentInfoFactory)
+    {
+        this.file = file;
+        this.fileContentInfoFactory = fileContentInfoFactory;
+    }
+
+    private FileContentThreadData getThreadData()
+    {
+        FileContentThreadData data = (FileContentThreadData) this.threadData.get();
+        if (data == null)
+        {
+            data = new FileContentThreadData();
+            this.threadData.set(data);
+        }
+        return data;
+    }
+
+    void streamOpened()
+    {
+        synchronized (this)
+        {
+            openStreams++;
+        }
+        ((AbstractFileSystem) file.getFileSystem()).streamOpened();
+    }
+
+    void streamClosed()
+    {
+        synchronized (this)
+        {
+            if (openStreams > 0)
+            {
+                openStreams--;
+                if (openStreams < 1)
+                {
+                    file.notifyAllStreamsClosed();
+                }
+            }
+        }
+        ((AbstractFileSystem) file.getFileSystem()).streamClosed();
+    }
+
+    /**
+     * Returns the file that this is the content of.
+     * @return the FileObject.
+     */
+    public FileObject getFile()
+    {
+        return file;
+    }
+
+    /**
+     * Returns the size of the content (in bytes).
+     * @return The size of the content (in bytes).
+     * @throws FileSystemException if an error occurs.
+     */
+    public long getSize() throws FileSystemException
+    {
+        // Do some checking
+        if (!file.getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/get-size-not-file.error", file);
+        }
+        /*
+        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 file.doGetContentSize();
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider/get-size.error", new Object[]{file}, exc);
+        }
+    }
+
+    /**
+     * Returns the last-modified timestamp.
+     * @return The last modified timestamp.
+     * @throws FileSystemException if an error occurs.
+     */
+    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 (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/get-last-modified-no-exist.error", file);
+        }
+        try
+        {
+            return file.doGetLastModifiedTime();
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/get-last-modified.error", file, e);
+        }
+    }
+
+    /**
+     * Sets the last-modified timestamp.
+     * @param modTime The last modified timestamp.
+     * @throws FileSystemException if an error occurs.
+     */
+    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 (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/set-last-modified-no-exist.error", file);
+        }
+        try
+        {
+            if (!file.doSetLastModTime(modTime))
+            {
+                throw new FileSystemException("vfs.provider/set-last-modified.error", file);
+            }
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/set-last-modified.error", file, e);
+        }
+    }
+
+    /**
+     * 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.
+     */
+    public boolean hasAttribute(final String attrName) throws FileSystemException
+    {
+        if (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/exists-attributes-no-exist.error", file);
+        }
+        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.
+     */
+    public Map getAttributes() throws FileSystemException
+    {
+        if (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/get-attributes-no-exist.error", file);
+        }
+        if (resetAttributes || roAttrs == null)
+        {
+            try
+            {
+                synchronized (this)
+                {
+                    attrs = file.doGetAttributes();
+                    roAttrs = Collections.unmodifiableMap(attrs);
+                    resetAttributes = false;
+                }
+            }
+            catch (final Exception e)
+            {
+                throw new FileSystemException("vfs.provider/get-attributes.error", file, e);
+            }
+        }
+        return roAttrs;
+    }
+
+    /**
+     * Used internally to flag situations where the file attributes should be
+     * reretrieved.
+     */
+    public void resetAttributes()
+    {
+        resetAttributes = true;
+    }
+
+    /**
+     * Lists the attributes of this file.
+     * @return An array of attribute names.
+     * @throws FileSystemException if an error occurs.
+     */
+    public String[] getAttributeNames() throws FileSystemException
+    {
+        getAttributes();
+        final Set names = attrs.keySet();
+        return (String[]) names.toArray(new String[names.size()]);
+    }
+
+    /**
+     * Gets the value of an attribute.
+     * @param attrName The attribute name.
+     * @return The value of the attribute or null.
+     * @throws FileSystemException if an error occurs.
+     */
+    public Object getAttribute(final String attrName)
+        throws FileSystemException
+    {
+        getAttributes();
+        return attrs.get(attrName);
+    }
+
+    /**
+     * 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.
+     */
+    public void setAttribute(final String attrName, final Object value)
+        throws FileSystemException
+    {
+        if (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/set-attribute-no-exist.error", new Object[]{attrName, file});
+        }
+        try
+        {
+            file.doSetAttribute(attrName, value);
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/set-attribute.error", new Object[]{attrName, file}, e);
+        }
+
+        if (attrs != null)
+        {
+            attrs.put(attrName, value);
+        }
+    }
+
+    /**
+     * Removes an attribute.
+     * @param attrName The name of the attribute to remove.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void removeAttribute(final String attrName) throws FileSystemException
+    {
+        if (!file.getType().hasAttributes())
+        {
+            throw new FileSystemException("vfs.provider/remove-attribute-no-exist.error", file);
+        }
+
+        try
+        {
+            file.doRemoveAttribute(attrName);
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/remove-attribute.error", new Object[]{attrName, file}, e);
+        }
+
+        if (attrs != null)
+        {
+            attrs.remove(attrName);
+        }
+    }
+
+    /**
+     * Returns the certificates used to sign this file.
+     * @return An array of Certificates.
+     * @throws FileSystemException if an error occurs.
+     */
+    public Certificate[] getCertificates() throws FileSystemException
+    {
+        if (!file.exists())
+        {
+            throw new FileSystemException("vfs.provider/get-certificates-no-exist.error", file);
+        }
+        /*
+        if (getThreadData().getState() == STATE_WRITING || getThreadData().getState() == STATE_RANDOM_ACCESS)
+        {
+            throw new FileSystemException("vfs.provider/get-certificates-writing.error", file);
+        }
+        */
+
+        try
+        {
+            final Certificate[] certs = file.doGetCertificates();
+            if (certs != null)
+            {
+                return certs;
+            }
+            else
+            {
+                return new Certificate[0];
+            }
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider/get-certificates.error", file, e);
+        }
+    }
+
+    /**
+     * Returns an input stream for reading the content.
+     * @return The InputStream
+     * @throws FileSystemException if an error occurs.
+     */
+    public InputStream getInputStream() 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
+        final InputStream instr = file.getInputStream();
+
+        final InputStream wrappedInstr = new FileContentInputStream(file, instr);
+
+        this.getThreadData().addInstr(wrappedInstr);
+        streamOpened();
+
+        // setState(STATE_OPENED);
+        return wrappedInstr;
+    }
+
+    /**
+     * 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.
+     */
+    public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException
+    {
+        /*
+        if (getThreadData().getState() != STATE_NONE)
+        {
+            throw new FileSystemException("vfs.provider/read-in-use.error", file);
+        }
+        */
+
+        // Get the content
+        final RandomAccessContent rastr = file.getRandomAccessContent(mode);
+
+        FileRandomAccessContent rac = new FileRandomAccessContent(file, rastr);
+        this.getThreadData().addRastr(rac);
+        streamOpened();
+
+        // setState(STATE_OPENED);
+        return rac;
+    }
+
+    /**
+     * Returns an output stream for writing the content.
+     * @return The OutputStream for the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public OutputStream getOutputStream() throws FileSystemException
+    {
+        return getOutputStream(false);
+    }
+
+    /**
+     * Returns an output stream for writing the content in append mode.
+     * @param bAppend true if the data written should be appended.
+     * @return The OutputStream for the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public OutputStream getOutputStream(boolean bAppend) throws FileSystemException
+    {
+        /*
+        if (getThreadData().getState() != STATE_NONE)
+        */
+        if (this.getThreadData().getOutstr() != null)
+        {
+            throw new FileSystemException("vfs.provider/write-in-use.error", file);
+        }
+
+        // Get the raw output stream
+        final OutputStream outstr = file.getOutputStream(bAppend);
+
+        // Create wrapper
+        this.getThreadData().setOutstr(new FileContentOutputStream(file, outstr));
+        streamOpened();
+
+        // setState(STATE_OPENED);
+        return this.getThreadData().getOutstr();
+    }
+
+    /**
+     * Closes all resources used by the content, including all streams, readers
+     * and writers.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void close() throws FileSystemException
+    {
+        try
+        {
+            // Close the input stream
+            while (getThreadData().getInstrsSize() > 0)
+            {
+                final FileContentInputStream instr = (FileContentInputStream) getThreadData().removeInstr(0);
+                instr.close();
+            }
+
+            // Close the randomAccess stream
+            while (getThreadData().getRastrsSize() > 0)
+            {
+                final RandomAccessContent ra = (RandomAccessContent) getThreadData().removeRastr(0);
+                try
+                {
+                    ra.close();
+                }
+                catch (IOException e)
+                {
+                    throw new FileSystemException(e);
+                }
+            }
+
+            // Close the output stream
+            if (this.getThreadData().getOutstr() != null)
+            {
+                this.getThreadData().closeOutstr();
+            }
+        }
+        finally
+        {
+            threadData.set(null);
+        }
+    }
+
+    /**
+     * Handles the end of input stream.
+     */
+    private void endInput(final FileContentInputStream instr)
+    {
+        getThreadData().removeInstr(instr);
+        streamClosed();
+        /*
+        if (!getThreadData().hasStreams())
+        {
+            setState(STATE_CLOSED);
+        }
+        */
+    }
+
+    /**
+     * Handles the end of random access.
+     */
+    private void endRandomAccess(RandomAccessContent rac)
+    {
+        getThreadData().removeRastr(rac);
+        streamClosed();
+        // setState(STATE_CLOSED);
+    }
+
+    /**
+     * Handles the end of output stream.
+     */
+    private void endOutput() throws Exception
+    {
+        streamClosed();
+
+        this.getThreadData().setOutstr(null);
+        // setState(STATE_CLOSED);
+
+        file.endOutput();
+    }
+
+    /*
+    private void setState(int state)
+    {
+        getThreadData().setState(state);
+    }
+    */
+
+    /**
+     * check if a input and/or output stream is open.<br />
+     * This checks only the scope of the current thread.
+     *
+     * @return true if this is the case
+     */
+    public boolean isOpen()
+    {
+        // return getThreadData().getState() == STATE_OPENED;
+        return getThreadData().hasStreams();
+    }
+
+    /**
+     * check if a input and/or output stream is open.<br />
+     * This checks all threads.
+     *
+     * @return true if this is the case
+     */
+    public boolean isOpenGlobal()
+    {
+        synchronized (this)
+        {
+            return openStreams > 0;
+        }
+    }
+
+    /**
+     * 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;
+        }
+
+        /**
+         * Closes this input stream.
+         */
+        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.
+         */
+        protected void onClose() throws IOException
+        {
+            try
+            {
+                super.onClose();
+            }
+            finally
+            {
+                endInput(this);
+            }
+        }
+    }
+
+    /**
+     * An input/output stream for reading/writing content on random positions
+     */
+    private final class FileRandomAccessContent extends MonitorRandomAccessContent
+    {
+        // avoid gc
+        private final FileObject file;
+        private final RandomAccessContent content;
+
+        FileRandomAccessContent(final FileObject file, final RandomAccessContent content)
+        {
+            super(content);
+            this.file = file;
+            this.content = content;
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        protected void onClose() throws IOException
+        {
+            try
+            {
+                super.onClose();
+            }
+            finally
+            {
+                endRandomAccess(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;
+        }
+
+        /**
+         * Closes this output stream.
+         */
+        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.
+         */
+        protected void onClose() throws IOException
+        {
+            try
+            {
+                super.onClose();
+            }
+            finally
+            {
+                try
+                {
+                    endOutput();
+                }
+                catch (Exception e)
+                {
+                    throw new FileSystemException("vfs.provider/close-outstr.error", file, e);
+                }
+            }
+        }
+    }
+
+    /**
+     * get the content info. e.g. content-type, content-encoding
+     * @return The FileContentInfo.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileContentInfo getContentInfo() throws FileSystemException
+    {
+        if (fileContentInfo == null)
+        {
+            fileContentInfo = fileContentInfoFactory.create(this);
+        }
+
+        return fileContentInfo;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileSelectorInfo.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileSelectorInfo.java
new file mode 100644
index 0000000..3cfb9cf
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultFileSelectorInfo.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelectInfo;
+
+/**
+ * A default {@link FileSelectInfo} implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+final class DefaultFileSelectorInfo
+    implements FileSelectInfo
+{
+    private FileObject baseFolder;
+    private FileObject file;
+    private int depth;
+
+    public FileObject getBaseFolder()
+    {
+        return baseFolder;
+    }
+
+    public void setBaseFolder(final FileObject baseFolder)
+    {
+        this.baseFolder = baseFolder;
+    }
+
+    public FileObject getFile()
+    {
+        return file;
+    }
+
+    public void setFile(final FileObject file)
+    {
+        this.file = file;
+    }
+
+    public int getDepth()
+    {
+        return depth;
+    }
+
+    public void setDepth(final int depth)
+    {
+        this.depth = depth;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLConnection.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLConnection.java
new file mode 100644
index 0000000..a65c410
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLConnection.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * A default URL connection that will work for most file systems.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public final class DefaultURLConnection
+    extends URLConnection
+{
+    private final FileContent content;
+
+    public DefaultURLConnection(final URL url,
+                                final FileContent content)
+    {
+        super(url);
+        this.content = content;
+    }
+
+    public void connect()
+    {
+        connected = true;
+    }
+
+    public InputStream getInputStream()
+        throws IOException
+    {
+        return content.getInputStream();
+    }
+
+    public OutputStream getOutputStream()
+        throws IOException
+    {
+        return content.getOutputStream();
+    }
+
+
+    public long getLastModified()
+    {
+        try
+        {
+            return content.getLastModifiedTime();
+        }
+        catch (FileSystemException fse)
+        {
+            // Ignore the exception
+        }
+
+        return -1;
+    }
+
+    public int getContentLength()
+    {
+        try
+        {
+            return (int) content.getSize();
+        }
+        catch (FileSystemException fse)
+        {
+            // Ignore the exception
+        }
+
+        return -1;
+    }
+
+    public String getContentType()
+    {
+        try
+        {
+            return content.getContentInfo().getContentType();
+        }
+        catch (FileSystemException e)
+        {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public String getContentEncoding()
+    {
+        try
+        {
+            return content.getContentInfo().getContentEncoding();
+        }
+        catch (FileSystemException e)
+        {
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    /*
+    public String getHeaderField(String name)
+    {
+        try
+        {
+            if (content.getFile().getFileSystem().hasCapability(Capability.ATTRIBUTES))
+            {
+                String value = (String) content.getAttribute(name);
+                if (value != null)
+                {
+                    return value;
+                }
+            }
+
+            return null;
+        }
+        catch (FileSystemException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+    */
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLStreamHandler.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLStreamHandler.java
new file mode 100644
index 0000000..250ab94
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DefaultURLStreamHandler.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * A default URL stream handler that will work for most file systems.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultURLStreamHandler
+    extends URLStreamHandler
+{
+    private final VfsComponentContext context;
+    private final FileSystemOptions fileSystemOptions;
+
+    public DefaultURLStreamHandler(final VfsComponentContext context)
+    {
+        this(context, null);
+    }
+
+    public DefaultURLStreamHandler(final VfsComponentContext context, final FileSystemOptions fileSystemOptions)
+    {
+        this.context = context;
+        this.fileSystemOptions = fileSystemOptions;
+    }
+
+    protected URLConnection openConnection(final URL url)
+        throws IOException
+    {
+        final FileObject entry = context.resolveFile(url.toExternalForm(), fileSystemOptions);
+        return new DefaultURLConnection(url, entry.getContent());
+    }
+
+    protected void parseURL(final URL u,
+                            final String spec,
+                            final int start,
+                            final int limit)
+    {
+        try
+        {
+            FileObject old = context.resolveFile(u.toExternalForm(), fileSystemOptions);
+
+            FileObject newURL;
+            if (start > 0 && spec.charAt(start - 1) == ':')
+            {
+                newURL = context.resolveFile(old, spec, fileSystemOptions);
+            }
+            else
+            {
+                if (old.getType() == FileType.FILE && old.getParent() != null)
+                {
+                    // for files we have to resolve relative
+                    newURL = old.getParent().resolveFile(spec);
+                }
+                else
+                {
+                    newURL = old.resolveFile(spec);
+                }
+            }
+
+            final String url = newURL.getName().getURI();
+            final StringBuffer filePart = new StringBuffer();
+            final String protocolPart = UriParser.extractScheme(url, filePart);
+
+            setURL(u, protocolPart, "", -1, null, null, filePart.toString(), null, null);
+        }
+        catch (FileSystemException fse)
+        {
+            // This is rethrown to MalformedURLException in URL anyway
+            throw new RuntimeException(fse.getMessage());
+        }
+    }
+
+    protected String toExternalForm(final URL u)
+    {
+        return u.getProtocol() + ":" + u.getFile();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DelegateFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DelegateFileObject.java
new file mode 100644
index 0000000..9322c3d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/DelegateFileObject.java
@@ -0,0 +1,436 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.util.WeakRefFileListener;
+import org.apache.commons.vfs.util.RandomAccessMode;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileNotFolderException;
+import org.apache.commons.vfs.FileChangeEvent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.RandomAccessContent;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.cert.Certificate;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A file backed by another file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Revision$ $Date$
+ * @todo Extract subclass that overlays the children
+ */
+public class DelegateFileObject
+    extends AbstractFileObject
+    implements FileListener
+{
+    private FileObject file;
+    private final Set children = new HashSet();
+    private boolean ignoreEvent;
+
+    public DelegateFileObject(final FileName name,
+                              final AbstractFileSystem fileSystem,
+                              final FileObject file) throws FileSystemException
+    {
+        super(name, fileSystem);
+        this.file = file;
+        if (file != null)
+        {
+            WeakRefFileListener.installListener(file, this);
+        }
+    }
+
+    /**
+     * Get access to the delegated file.
+     * @return The FileObject.
+     */
+    public FileObject getDelegateFile()
+    {
+        return file;
+    }
+
+    /**
+     * Adds a child to this file.
+     * @param baseName The base FileName.
+     * @param type The FileType.
+     * @throws Exception if an error occurs.
+     */
+    public void attachChild(final FileName baseName, final FileType type) throws Exception
+    {
+        final FileType oldType = doGetType();
+        if (children.add(baseName.getBaseName()))
+        {
+            childrenChanged(baseName, type);
+        }
+        maybeTypeChanged(oldType);
+    }
+
+    /**
+     * Attaches or detaches the target file.
+     * @param file The FileObject.
+     * @throws Exception if an error occurs.
+     */
+    public void setFile(final FileObject file) throws Exception
+    {
+        final FileType oldType = doGetType();
+
+        if (file != null)
+        {
+            WeakRefFileListener.installListener(file, this);
+        }
+        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.
+     */
+    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();
+        }
+    }
+
+    /**
+     * Determines the type of the file, returns null if the file does not
+     * exist.
+     */
+    protected FileType doGetType() throws FileSystemException
+    {
+        if (file != null)
+        {
+            return file.getType();
+        }
+        else if (children.size() > 0)
+        {
+            return FileType.FOLDER;
+        }
+        else
+        {
+            return FileType.IMAGINARY;
+        }
+    }
+
+    /**
+     * Determines if this file can be read.
+     */
+    protected boolean doIsReadable() throws FileSystemException
+    {
+        if (file != null)
+        {
+            return file.isReadable();
+        }
+        else
+        {
+            return true;
+        }
+    }
+
+    /**
+     * Determines if this file can be written to.
+     */
+    protected boolean doIsWriteable() throws FileSystemException
+    {
+        if (file != null)
+        {
+            return file.isWriteable();
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Determines if this file is hidden.
+     */
+    protected boolean doIsHidden() throws FileSystemException
+    {
+        if (file != null)
+        {
+            return file.isHidden();
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        if (file != null)
+        {
+            final FileObject[] children;
+
+            try
+            {
+                children = file.getChildren();
+            }
+            // VFS-210
+            catch (FileNotFolderException e)
+            {
+                throw new FileNotFolderException(getName(), e);
+            }
+
+            final String[] childNames = new String[children.length];
+            for (int i = 0; i < children.length; i++)
+            {
+                childNames[i] = children[i].getName().getBaseName();
+            }
+            return childNames;
+        }
+        else
+        {
+            return (String[]) children.toArray(new String[children.size()]);
+        }
+    }
+
+    /**
+     * Creates this file as a folder.
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        ignoreEvent = true;
+        try
+        {
+            file.createFolder();
+        }
+        finally
+        {
+            ignoreEvent = false;
+        }
+    }
+
+    /**
+     * Deletes the file.
+     */
+    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}.
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        return file.getContent().getSize();
+    }
+
+    /**
+     * Returns the attributes of this file.
+     */
+    protected Map doGetAttributes()
+        throws Exception
+    {
+        return file.getContent().getAttributes();
+    }
+
+    /**
+     * Sets an attribute of this file.
+     */
+    protected void doSetAttribute(final String atttrName,
+                                  final Object value)
+        throws Exception
+    {
+        file.getContent().setAttribute(atttrName, value);
+    }
+
+    /**
+     * Returns the certificates of this file.
+     */
+    protected Certificate[] doGetCertificates() throws Exception
+    {
+        return file.getContent().getCertificates();
+    }
+
+    /**
+     * Returns the last-modified time of this file.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        return file.getContent().getLastModifiedTime();
+    }
+
+    /**
+     * Sets the last-modified time of this file.
+     */
+    protected boolean doSetLastModTime(final long modtime)
+        throws Exception
+    {
+        file.getContent().setLastModifiedTime(modtime);
+        return true;
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        return file.getContent().getInputStream();
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        return file.getContent().getOutputStream(bAppend);
+    }
+
+    /**
+     * Called when a file is created.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileCreated(final FileChangeEvent event) throws Exception
+    {
+        if (event.getFile() != file)
+        {
+            return;
+        }
+        if (!ignoreEvent)
+        {
+            handleCreate(file.getType());
+        }
+    }
+
+    /**
+     * Called when a file is deleted.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileDeleted(final FileChangeEvent event) throws Exception
+    {
+        if (event.getFile() != file)
+        {
+            return;
+        }
+        if (!ignoreEvent)
+        {
+            handleDelete();
+        }
+    }
+
+    /**
+     * Called when a file is changed.
+     * <p/>
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileChanged(FileChangeEvent event) throws Exception
+    {
+        if (event.getFile() != file)
+        {
+            return;
+        }
+        if (!ignoreEvent)
+        {
+            handleChanged();
+        }
+    }
+
+    /**
+     * Close the delegated file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void close() throws FileSystemException
+    {
+        super.close();
+
+        if (file != null)
+        {
+            file.close();
+        }
+    }
+
+    /**
+     * Refresh file information.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void refresh() throws FileSystemException
+    {
+        super.refresh();
+        if (file != null)
+        {
+            file.refresh();
+        }
+    }
+
+    protected FileContentInfo doGetContentInfo() throws Exception
+    {
+        return file.getContent().getContentInfo();
+    }
+
+    /**
+     * Renames the file.
+     */
+    protected void doRename(FileObject newFile)
+        throws Exception
+    {
+        file.moveTo(((DelegateFileObject) newFile).file);
+    }
+
+    /**
+     * Removes an attribute of this file.
+     */
+    protected void doRemoveAttribute(final String atttrName)
+        throws Exception
+    {
+        file.getContent().removeAttribute(atttrName);
+    }
+
+    /**
+     * Creates access to the file for random i/o.
+     */
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        return file.getContent().getRandomAccessContent(mode);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileContentThreadData.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileContentThreadData.java
new file mode 100644
index 0000000..b02fa87
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileContentThreadData.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.RandomAccessContent;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * Holds the data which needs to be local to the current thread
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class FileContentThreadData
+{
+    // private int state = DefaultFileContent.STATE_CLOSED;
+
+    private final ArrayList instrs = new ArrayList();
+    private final ArrayList rastrs = new ArrayList();
+    private DefaultFileContent.FileContentOutputStream outstr;
+
+    FileContentThreadData()
+    {
+    }
+
+    /*
+    int getState()
+    {
+        return state;
+    }
+
+    void setState(int state)
+    {
+        this.state = state;
+    }
+    */
+
+    void addInstr(InputStream is)
+    {
+        this.instrs.add(is);
+    }
+
+    void setOutstr(DefaultFileContent.FileContentOutputStream os)
+    {
+        this.outstr = os;
+    }
+
+    DefaultFileContent.FileContentOutputStream getOutstr()
+    {
+        return this.outstr;
+    }
+
+    void addRastr(RandomAccessContent ras)
+    {
+        this.rastrs.add(ras);
+    }
+
+    int getInstrsSize()
+    {
+        return this.instrs.size();
+    }
+
+    public Object removeInstr(int pos)
+    {
+        return this.instrs.remove(pos);
+    }
+
+    public void removeInstr(InputStream instr)
+    {
+        this.instrs.remove(instr);
+    }
+
+    public Object removeRastr(int pos)
+    {
+        return this.rastrs.remove(pos);
+    }
+
+    public void removeRastr(RandomAccessContent ras)
+    {
+        this.rastrs.remove(ras);
+    }
+
+    public boolean hasStreams()
+    {
+        return instrs.size() > 0 || outstr != null || rastrs.size() > 0;
+    }
+
+    public void closeOutstr() throws FileSystemException
+    {
+        outstr.close();
+        outstr = null;
+    }
+
+    int getRastrsSize()
+    {
+        return rastrs.size();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileNameParser.java
new file mode 100644
index 0000000..a7a662a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileNameParser.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * Provides methods to parse a filename into a {@link org.apache.commons.vfs.FileName}.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public interface FileNameParser
+{
+    /**
+     * Check if a character needs encoding (%nn).
+     * @param ch the character
+     * @return true if character should be encoded
+     */
+    boolean encodeCharacter(char ch);
+
+    /**
+     * parses a String into a filename.
+     * @param context The component context.
+     * @param base The base FileName.
+     * @param filename The target file name.
+     * @return A FileName that represents the taret file.
+     * @throws FileSystemException if an error occurs parsing the URI.
+     */
+    FileName parseUri(final VfsComponentContext context, final FileName base, final String filename)
+            throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileProvider.java
new file mode 100644
index 0000000..45231ca
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileProvider.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+
+import java.util.Collection;
+
+
+/**
+ * A file provider.  Each file provider is responsible for handling files for
+ * a particular URI scheme.
+ * <p/>
+ * <p>A file provider may also implement {@link VfsComponent}.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+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(final FileObject baseFile, final String uri, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    /**
+     * Creates a layered file system.
+     *
+     * @param scheme            The URI scheme for the layered file system.
+     * @param file              The file to build the file system on.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return A FileObject in the file system.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject createFileSystem(String scheme, FileObject file, FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    /**
+     * Gets the configbuilder useable to collect the needed fileSystemOptions.
+     * @return a FileSystemConfigBuilder for the particular file system.
+     */
+    FileSystemConfigBuilder getConfigBuilder();
+
+    /**
+     * Get the filesystem capabilities.<br>
+     * These are the same as on the filesystem, but available before the first filesystem was
+     * instanciated.
+     * @return a Collection of the file systems Capabilities.
+     */
+    Collection getCapabilities();
+
+    /**
+     * Parse the URI into a FileName.
+     * @param root The base FileName.
+     * @param uri The file to be accessed.
+     * @return A FileName representing the target file.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileName parseUri(FileName root, String uri) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileReplicator.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileReplicator.java
new file mode 100644
index 0000000..d715bdd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileReplicator.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.File;
+
+/**
+ * Responsible for making local replicas of files.
+ * <p/>
+ * <p>A file replicator may also implement {@link VfsComponent}.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface FileReplicator
+{
+    /**
+     * Creates a local copy of the file, and all its descendents.
+     *
+     * @param srcFile  The file to copy.
+     * @param selector Selects the files to copy.
+     * @return The local copy of the source file.
+     * @throws FileSystemException If the source files does not exist, or on error copying.
+     */
+    File replicateFile(FileObject srcFile, FileSelector selector)
+        throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileSystemKey.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileSystemKey.java
new file mode 100644
index 0000000..efaba9c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/FileSystemKey.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * Used to identify a filesystem
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+class FileSystemKey implements Comparable
+{
+    private static final FileSystemOptions EMPTY_OPTIONS = new FileSystemOptions();
+
+    private final Comparable key;
+    private final FileSystemOptions fileSystemOptions;
+
+    FileSystemKey(final Comparable key, final FileSystemOptions fileSystemOptions)
+    {
+        this.key = key;
+        if (fileSystemOptions != null)
+        {
+            this.fileSystemOptions = fileSystemOptions;
+        }
+        else
+        {
+            this.fileSystemOptions = EMPTY_OPTIONS;
+        }
+    }
+
+    public int compareTo(Object o)
+    {
+        FileSystemKey fk = (FileSystemKey) o;
+
+        int ret = key.compareTo(fk.key);
+        if (ret != 0)
+        {
+            // other filesystem
+            return ret;
+        }
+
+        return fileSystemOptions.compareTo(fk.fileSystemOptions);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/GenericFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/GenericFileName.java
new file mode 100644
index 0000000..05ca2b7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/GenericFileName.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * A file name that represents a 'generic' URI, as per RFC 2396.  Consists of
+ * a scheme, userinfo (typically username and password), hostname, port, and
+ * path.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class GenericFileName extends AbstractFileName
+{
+    private static final char[] USERNAME_RESERVED = {':', '@', '/'};
+    private static final char[] PASSWORD_RESERVED = {'@', '/', '?'};
+    private final String userName;
+    private final String hostName;
+    private final int defaultPort;
+    private final String password;
+    private final int port;
+
+    protected GenericFileName(final String scheme,
+                              final String hostName,
+                              final int port,
+                              final int defaultPort,
+                              final String userName,
+                              final String password,
+                              final String path,
+                              final FileType type
+    )
+    {
+        super(scheme, path, type);
+        this.hostName = hostName;
+        this.defaultPort = defaultPort;
+        this.password = password;
+        this.userName = userName;
+        if (port > 0)
+        {
+            this.port = port;
+        }
+        else
+        {
+            this.port = getDefaultPort();
+        }
+    }
+
+    /**
+     * Returns the user name part of this name.
+     * @return The user name.
+     */
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    /**
+     * Returns the password part of this name.
+     * @return The password.
+     */
+    public String getPassword()
+    {
+        return password;
+    }
+
+    /**
+     * Returns the host name part of this name.
+     * @return The host name.
+     */
+    public String getHostName()
+    {
+        return hostName;
+    }
+
+    /**
+     * Returns the port part of this name.
+     * @return The port number.
+     */
+    public int getPort()
+    {
+        return port;
+    }
+
+    /**
+     * Returns the default port for this file name.
+     * @return The default port number.
+     */
+    public int getDefaultPort()
+    {
+        return defaultPort;
+    }
+
+    /**
+     * Create a FileName.
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The created FileName.
+     */
+    public FileName createName(String absPath, FileType type)
+    {
+        return new GenericFileName(
+            getScheme(),
+            hostName,
+            port,
+            defaultPort,
+            userName,
+            password,
+            absPath,
+            type);
+    }
+
+    /**
+     * Builds the root URI for this file name.
+     */
+    protected void appendRootUri(final StringBuffer buffer, boolean addPassword)
+    {
+        buffer.append(getScheme());
+        buffer.append("://");
+        appendCredentials(buffer, addPassword);
+        buffer.append(hostName);
+        if (port != getDefaultPort())
+        {
+            buffer.append(':');
+            buffer.append(port);
+        }
+    }
+
+    /**
+     * append the user credentials
+     */
+    protected void appendCredentials(StringBuffer buffer, boolean addPassword)
+    {
+        if (userName != null && userName.length() != 0)
+        {
+            UriParser.appendEncoded(buffer, userName, USERNAME_RESERVED);
+            if (password != null && password.length() != 0)
+            {
+                buffer.append(':');
+                if (addPassword)
+                {
+                    UriParser.appendEncoded(buffer, password, PASSWORD_RESERVED);
+                }
+                else
+                {
+                    buffer.append("***");
+                }
+            }
+            buffer.append('@');
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/HostFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/HostFileNameParser.java
new file mode 100644
index 0000000..4ba65f4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/HostFileNameParser.java
@@ -0,0 +1,312 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.util.Cryptor;
+import org.apache.commons.vfs.util.CryptorFactory;
+
+/**
+ * Implementation for any url based filesystem.<br />
+ * Parses the url into user/password/host/port/path<br />
+ * Does not handle a query string (after ?)
+ *
+ * @author imario@apache.org
+ * @version $Revision$ $Date$
+ * @see URLFileNameParser URLFileNameParser for the implementation which also handles the query string too
+ */
+public class HostFileNameParser extends AbstractFileNameParser
+{
+    private final int defaultPort;
+
+    public HostFileNameParser(final int defaultPort)
+    {
+        this.defaultPort = defaultPort;
+    }
+
+    public int getDefaultPort()
+    {
+        return defaultPort;
+    }
+
+    public boolean encodeCharacter(char ch)
+    {
+        return super.encodeCharacter(ch);
+    }
+
+    public FileName parseUri(final VfsComponentContext context, FileName base, final String filename)
+            throws FileSystemException
+    {
+        // FTP URI are generic URI (as per RFC 2396)
+        final StringBuffer name = new StringBuffer();
+
+        // Extract the scheme and authority parts
+        final Authority auth = extractToPath(filename, name);
+
+        // Decode and normalise the file name
+        UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
+        FileType fileType = UriParser.normalisePath(name);
+        final String path = name.toString();
+
+        return new GenericFileName(
+            auth.scheme,
+            auth.hostName,
+            auth.port,
+            defaultPort,
+            auth.userName,
+            auth.password,
+            path,
+            fileType);
+    }
+
+    /**
+     * Extracts the scheme, userinfo, hostname and port components of a
+     * generic URI.
+     *
+     * @param uri  The absolute URI to parse.
+     * @param name Used to return the remainder of the URI.
+     */
+    protected Authority extractToPath(final String uri,
+                                      final StringBuffer name)
+        throws FileSystemException
+    {
+        final Authority auth = new Authority();
+
+        // Extract the scheme
+        auth.scheme = UriParser.extractScheme(uri, name);
+
+        // Expecting "//"
+        if (name.length() < 2 || name.charAt(0) != '/' || name.charAt(1) != '/')
+        {
+            throw new FileSystemException("vfs.provider/missing-double-slashes.error", uri);
+        }
+        name.delete(0, 2);
+
+        // Extract userinfo, and split into username and password
+        final String userInfo = extractUserInfo(name);
+        final String userName;
+        final String password;
+        if (userInfo != null)
+        {
+            int idx = userInfo.indexOf(':');
+            if (idx == -1)
+            {
+                userName = userInfo;
+                password = null;
+            }
+            else
+            {
+                userName = userInfo.substring(0, idx);
+                password = userInfo.substring(idx + 1);
+            }
+        }
+        else
+        {
+            userName = null;
+            password = null;
+        }
+        auth.userName = UriParser.decode(userName);
+        auth.password = UriParser.decode(password);
+
+        if (auth.password != null && auth.password.startsWith("{") && auth.password.endsWith("}"))
+        {
+            try
+            {
+                Cryptor cryptor = CryptorFactory.getCryptor();
+                auth.password = cryptor.decrypt(auth.password.substring(1, auth.password.length() - 1));
+            }
+            catch (Exception ex)
+            {
+                throw new FileSystemException("Unable to decrypt password", ex);
+            }
+        }
+
+        // Extract hostname, and normalise (lowercase)
+        final String hostName = extractHostName(name);
+        if (hostName == null)
+        {
+            throw new FileSystemException("vfs.provider/missing-hostname.error", uri);
+        }
+        auth.hostName = hostName.toLowerCase();
+
+        // Extract port
+        auth.port = extractPort(name, uri);
+
+        // Expecting '/' or empty name
+        if (name.length() > 0 && name.charAt(0) != '/')
+        {
+            throw new FileSystemException("vfs.provider/missing-hostname-path-sep.error", uri);
+        }
+
+        return auth;
+    }
+
+    /**
+     * Extracts the user info from a URI.  The scheme:// part has been removed
+     * already.
+     */
+    protected String extractUserInfo(final StringBuffer name)
+    {
+        final int maxlen = name.length();
+        for (int pos = 0; pos < maxlen; pos++)
+        {
+            final char ch = name.charAt(pos);
+            if (ch == '@')
+            {
+                // Found the end of the user info
+                String userInfo = name.substring(0, pos);
+                name.delete(0, pos + 1);
+                return userInfo;
+            }
+            if (ch == '/' || ch == '?')
+            {
+                // Not allowed in user info
+                break;
+            }
+        }
+
+        // Not found
+        return null;
+    }
+
+    /**
+     * Extracts the hostname from a URI.  The scheme://userinfo@ part has
+     * been removed.
+     */
+    protected String extractHostName(final StringBuffer name)
+    {
+        final int maxlen = name.length();
+        int pos = 0;
+        for (; pos < maxlen; pos++)
+        {
+            final char ch = name.charAt(pos);
+            if (ch == '/' || ch == ';' || ch == '?' || ch == ':'
+                || ch == '@' || ch == '&' || ch == '=' || ch == '+'
+                || ch == '$' || ch == ',')
+            {
+                break;
+            }
+        }
+        if (pos == 0)
+        {
+            return null;
+        }
+
+        final String hostname = name.substring(0, pos);
+        name.delete(0, pos);
+        return hostname;
+    }
+
+    /**
+     * Extracts the port from a URI.  The scheme://userinfo@hostname
+     * part has been removed.
+     *
+     * @return The port, or -1 if the URI does not contain a port.
+     */
+    protected int extractPort(final StringBuffer name, final String uri) throws FileSystemException
+    {
+        if (name.length() < 1 || name.charAt(0) != ':')
+        {
+            return -1;
+        }
+
+        final int maxlen = name.length();
+        int pos = 1;
+        for (; pos < maxlen; pos++)
+        {
+            final char ch = name.charAt(pos);
+            if (ch < '0' || ch > '9')
+            {
+                break;
+            }
+        }
+
+        final String port = name.substring(1, pos);
+        name.delete(0, pos);
+        if (port.length() == 0)
+        {
+            throw new FileSystemException("vfs.provider/missing-port.error", uri);
+        }
+
+        return Integer.parseInt(port);
+    }
+
+    /**
+     * Parsed authority info (scheme, hostname, userinfo, port)
+     */
+    protected static class Authority
+    {
+        private String scheme;
+        private String hostName;
+        private String userName;
+        private String password;
+        private int port;
+
+        public String getScheme()
+        {
+            return scheme;
+        }
+
+        public void setScheme(String scheme)
+        {
+            this.scheme = scheme;
+        }
+
+        public String getHostName()
+        {
+            return hostName;
+        }
+
+        public void setHostName(String hostName)
+        {
+            this.hostName = hostName;
+        }
+
+        public String getUserName()
+        {
+            return userName;
+        }
+
+        public void setUserName(String userName)
+        {
+            this.userName = userName;
+        }
+
+        public String getPassword()
+        {
+            return password;
+        }
+
+        public void setPassword(String password)
+        {
+            this.password = password;
+        }
+
+        public int getPort()
+        {
+            return port;
+        }
+
+        public void setPort(int port)
+        {
+            this.port = port;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileName.java
new file mode 100644
index 0000000..eb53129
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileName.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * A file name for layered files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class LayeredFileName extends AbstractFileName
+{
+    private final FileName outerUri;
+
+    public LayeredFileName(final String scheme,
+                           final FileName outerUri,
+                           final String path,
+                           final FileType type)
+    {
+        super(scheme, path, type);
+        this.outerUri = outerUri;
+    }
+
+    /**
+     * Returns the URI of the outer file.
+     * @return The FileName.
+     */
+    public FileName getOuterName()
+    {
+        return outerUri;
+    }
+
+    /**
+     * Create a FileName.
+     * @param path The file URI.
+     * @param type The FileType.
+     * @return The FileName.
+     */
+    public FileName createName(String path, FileType type)
+    {
+        return new LayeredFileName(getScheme(), getOuterName(), path, type);
+    }
+
+    protected void appendRootUri(StringBuffer buffer, boolean addPassword)
+    {
+        buffer.append(getScheme());
+        buffer.append(":");
+        buffer.append(getOuterName().getURI());
+        buffer.append("!");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java
new file mode 100644
index 0000000..05d23b9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LayeredFileNameParser.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * Implementation for layered filesystems.
+ * <p/>
+ * Additionally encodes the '!' character.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class LayeredFileNameParser extends AbstractFileNameParser
+{
+    private static final LayeredFileNameParser INSTANCE = new LayeredFileNameParser();
+
+    /**
+     * Return the Parser.
+     * @return The Parser.
+     */
+    public static LayeredFileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+
+    /**
+     * Determines if a character should be encoded.
+     * @param ch The character to check.
+     * @return true if the character should be encoded.
+     */
+    public boolean encodeCharacter(char ch)
+    {
+        return super.encodeCharacter(ch) || ch == '!';
+    }
+
+    /**
+     * Parse the base and name into a FileName.
+     * @param context The component context.
+     * @param base The base FileName.
+     * @param filename The target file name.
+     * @return The constructed FileName.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName parseUri(final VfsComponentContext context, FileName base, final String filename)
+            throws FileSystemException
+    {
+        final StringBuffer name = new StringBuffer();
+
+        // Extract the scheme
+        final String scheme = UriParser.extractScheme(filename, name);
+
+        // Extract the Layered file URI
+        final String rootUriName = extractRootName(name);
+        FileName rootUri = null;
+        if (rootUriName != null)
+        {
+            rootUri = context.parseURI(rootUriName);
+        }
+
+        // Decode and normalise the path
+        UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
+        FileType fileType = UriParser.normalisePath(name);
+        final String path = name.toString();
+
+        return new LayeredFileName(scheme, rootUri, path, fileType);
+    }
+
+    /**
+     * Pops the root prefix off a URI, which has had the scheme removed.
+     */
+    protected String extractRootName(final StringBuffer uri)
+        throws FileSystemException
+    {
+        // Looking for <name>!<abspath> (staring at the end)
+        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
+        String prefix = uri.substring(0, pos);
+        if (pos < maxlen)
+        {
+            uri.delete(0, pos + 1);
+        }
+        else
+        {
+            uri.setLength(0);
+        }
+
+        return prefix;
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LocalFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LocalFileProvider.java
new file mode 100644
index 0000000..052ad05
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/LocalFileProvider.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.File;
+
+/**
+ * A file provider which handles local files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface LocalFileProvider
+    extends FileProvider
+{
+    /**
+     * Determines if a name is an absolute file name.
+     *
+     * @param name The name to test.
+     * @todo Move this to a general file name parser interface.
+     * @return true if the name is absolute.
+     */
+    boolean isAbsoluteLocalName(final String name);
+
+    /**
+     * Finds a local file, from its local name.
+     * @param name The name of the file to locate.
+     * @return The FileObject for the file.
+     * @throws FileSystemException if an error occurs.
+     *
+     */
+    FileObject findLocalFile(final String name)
+        throws FileSystemException;
+
+    /**
+     * Converts from java.io.File to FileObject.
+     * @param file The File for the file.
+     * @return The FileObject for the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject findLocalFile(final File file)
+        throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/TemporaryFileStore.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/TemporaryFileStore.java
new file mode 100644
index 0000000..a9c6603
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/TemporaryFileStore.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.File;
+
+/**
+ * Manages a repository of temporary local files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface TemporaryFileStore
+{
+    /**
+     * Allocates a new temporary file.  The file (and all its descendents)
+     * will be deleted when this store is closed.
+     *
+     * @param basename The name of the file.
+     * @return The temporary file.
+     * @throws FileSystemException if an error occurs.
+     */
+    File allocateFile(String basename) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileName.java
new file mode 100644
index 0000000..7e7d3b2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileName.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.util.URIUtil;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class URLFileName extends GenericFileName
+{
+    private static final int BUFFSZ = 250;
+
+    private final String queryString;
+
+    public URLFileName(final String scheme,
+                       final String hostName,
+                       final int port,
+                       final int defaultPort,
+                       final String userName,
+                       final String password,
+                       final String path,
+                       final FileType type,
+                       final String queryString)
+    {
+        super(scheme, hostName, port, defaultPort, userName, password, path, type);
+        this.queryString = queryString;
+    }
+
+    /**
+     * Get the query string.
+     *
+     * @return the query string part of the filename
+     */
+    public String getQueryString()
+    {
+        return queryString;
+    }
+
+    /**
+     * Get the path and query string e.g. /path/servlet?param1=true.
+     *
+     * @return the path and its query string
+     */
+    public String getPathQuery()
+    {
+        StringBuffer sb = new StringBuffer(BUFFSZ);
+        sb.append(getPath());
+        sb.append("?");
+        sb.append(getQueryString());
+
+        return sb.toString();
+    }
+
+    /**
+     * Get the path encoded suitable for url like filesystem e.g. (http, webdav).
+     *
+     * @param charset the charset used for the path encoding
+     * @return The encoded path.
+     * @throws URIException If an error occurs encoding the URI.
+     * @throws FileSystemException If some other error occurs.
+     */
+    public String getPathQueryEncoded(String charset) throws URIException, FileSystemException
+    {
+        if (getQueryString() == null)
+        {
+            if (charset != null)
+            {
+                return URIUtil.encodePath(getPathDecoded(), charset);
+            }
+            else
+            {
+                return URIUtil.encodePath(getPathDecoded());
+            }
+        }
+
+        StringBuffer sb = new StringBuffer(BUFFSZ);
+        if (charset != null)
+        {
+            sb.append(URIUtil.encodePath(getPathDecoded(), charset));
+        }
+        else
+        {
+            sb.append(URIUtil.encodePath(getPathDecoded()));
+        }
+        sb.append("?");
+        sb.append(getQueryString());
+        return sb.toString();
+    }
+
+    /**
+     * Create a FileName.
+     * @param absPath The absolute path.
+     * @param type The FileType.
+     * @return The FileName
+     */
+    public FileName createName(final String absPath, FileType type)
+    {
+        return new URLFileName(getScheme(),
+            getHostName(),
+            getPort(),
+            getDefaultPort(),
+            getUserName(),
+            getPassword(),
+            absPath,
+            type,
+            getQueryString());
+    }
+
+    /**
+     * Append query string to the uri.
+     *
+     * @return the uri
+     */
+    protected String createURI()
+    {
+        if (getQueryString() != null)
+        {
+            StringBuffer sb = new StringBuffer(BUFFSZ);
+            sb.append(super.createURI());
+            sb.append("?");
+            sb.append(getQueryString());
+
+            return sb.toString();
+        }
+
+        return super.createURI();
+    }
+
+    /**
+     * Encode a URI.
+     * @param charset The character set.
+     * @return The encoded URI
+     * @throws FileSystemException if some other exception occurs.
+     * @throws URIException if an exception occurs encoding the URI.
+     */
+    public String getURIEncoded(String charset) throws FileSystemException, URIException
+    {
+        StringBuffer sb = new StringBuffer(BUFFSZ);
+        appendRootUri(sb, true);
+        sb.append(getPathQueryEncoded(charset));
+        return sb.toString();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileNameParser.java
new file mode 100644
index 0000000..44b1768
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/URLFileNameParser.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * Implementation for any url based filesystem.<br />
+ * Parses the url into user/password/host/port/path/queryString<br />
+ *
+ * @author imario@apache.org
+ * @version $Revision$ $Date$
+ */
+public class URLFileNameParser extends HostFileNameParser
+{
+    public URLFileNameParser(final int defaultPort)
+    {
+        super(defaultPort);
+    }
+
+    public boolean encodeCharacter(char ch)
+    {
+        return super.encodeCharacter(ch) || ch == '?';
+    }
+
+    public FileName parseUri(final VfsComponentContext context, FileName base, final String filename)
+            throws FileSystemException
+    {
+        // FTP URI are generic URI (as per RFC 2396)
+        final StringBuffer name = new StringBuffer();
+
+        // Extract the scheme and authority parts
+        final Authority auth = extractToPath(filename, name);
+
+        // Extract the queryString
+        String queryString = UriParser.extractQueryString(name);
+
+        // Decode and normalise the file name
+        UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
+        FileType fileType = UriParser.normalisePath(name);
+        final String path = name.toString();
+
+        return new URLFileName(
+            auth.getScheme(),
+            auth.getHostName(),
+            auth.getPort(),
+            getDefaultPort(),
+            auth.getUserName(),
+            auth.getPassword(),
+            path,
+            fileType,
+            queryString);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/UriParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/UriParser.java
new file mode 100644
index 0000000..145cd0f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/UriParser.java
@@ -0,0 +1,543 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.VFS;
+import org.apache.commons.vfs.util.Os;
+
+/**
+ * Utilities for dealing with URIs. See RFC 2396 for details.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date: 2005-10-13 21:11:33 +0200 (Do, 13 Okt
+ *          2005) $
+ */
+public final class UriParser
+{
+    /**
+     * The set of valid separators. These are all converted to the normalised
+     * one. Does <i>not</i> contain the normalised separator
+     */
+    // public static final char[] separators = {'\\'};
+    public static final char TRANS_SEPARATOR = '\\';
+
+    /**
+     * The normalised separator to use.
+     */
+    private static final char SEPARATOR_CHAR = FileName.SEPARATOR_CHAR;
+
+    private static final int HEX_BASE = 16;
+
+    private static final int BITS_IN_HALF_BYTE = 4;
+
+    private static final char LOW_MASK = 0x0F;
+
+    private UriParser()
+    {
+    }
+
+    /**
+     * Extracts the first element of a path.
+     * @param name StringBuffer containing the path.
+     * @return The first element of the path.
+     */
+    public static String extractFirstElement(final StringBuffer name)
+    {
+        final int len = name.length();
+        if (len < 1)
+        {
+            return null;
+        }
+        int startPos = 0;
+        if (name.charAt(0) == SEPARATOR_CHAR)
+        {
+            startPos = 1;
+        }
+        for (int pos = startPos; pos < len; pos++)
+        {
+            if (name.charAt(pos) == SEPARATOR_CHAR)
+            {
+                // Found a separator
+                final String elem = name.substring(startPos, pos);
+                name.delete(startPos, pos + 1);
+                return elem;
+            }
+        }
+
+        // No separator
+        final String elem = name.substring(startPos);
+        name.setLength(0);
+        return elem;
+    }
+
+    /**
+     * Normalises a path. Does the following:
+     * <ul>
+     * <li>Removes empty path elements.
+     * <li>Handles '.' and '..' elements.
+     * <li>Removes trailing separator.
+     * </ul>
+     *
+     * Its assumed that the separators are already fixed.
+     *
+     * @param path The path to normalize.
+     * @return The FileType.
+     * @throws FileSystemException if an error occurs.
+     *
+     *  @see #fixSeparators
+     */
+    public static FileType normalisePath(final StringBuffer path)
+            throws FileSystemException
+    {
+        FileType fileType = FileType.FOLDER;
+        if (path.length() == 0)
+        {
+            return fileType;
+        }
+
+        if (path.charAt(path.length() - 1) != '/')
+        {
+            fileType = FileType.FILE;
+        }
+
+        // Adjust separators
+        // fixSeparators(path);
+
+        // Determine the start of the first element
+        int startFirstElem = 0;
+        if (path.charAt(0) == SEPARATOR_CHAR)
+        {
+            if (path.length() == 1)
+            {
+                return fileType;
+            }
+            startFirstElem = 1;
+        }
+
+        // Iterate over each element
+        int startElem = startFirstElem;
+        int maxlen = path.length();
+        while (startElem < maxlen)
+        {
+            // Find the end of the element
+            int endElem = startElem;
+            for (; endElem < maxlen && path.charAt(endElem) != SEPARATOR_CHAR; endElem++)
+            {
+            }
+
+            final int elemLen = endElem - startElem;
+            if (elemLen == 0)
+            {
+                // An empty element - axe it
+                path.delete(endElem, endElem + 1);
+                maxlen = path.length();
+                continue;
+            }
+            if (elemLen == 1 && path.charAt(startElem) == '.')
+            {
+                // A '.' element - axe it
+                path.delete(startElem, endElem + 1);
+                maxlen = path.length();
+                continue;
+            }
+            if (elemLen == 2 && path.charAt(startElem) == '.'
+                    && path.charAt(startElem + 1) == '.')
+            {
+                // A '..' element - remove the previous element
+                if (startElem == startFirstElem)
+                {
+                    // Previous element is missing
+                    throw new FileSystemException(
+                            "vfs.provider/invalid-relative-path.error");
+                }
+
+                // Find start of previous element
+                int pos = startElem - 2;
+                for (; pos >= 0 && path.charAt(pos) != SEPARATOR_CHAR; pos--)
+                {
+                }
+                startElem = pos + 1;
+
+                path.delete(startElem, endElem + 1);
+                maxlen = path.length();
+                continue;
+            }
+
+            // A regular element
+            startElem = endElem + 1;
+        }
+
+        // Remove trailing separator
+        if (!VFS.isUriStyle())
+        {
+            if (maxlen > 0 && path.charAt(maxlen - 1) == SEPARATOR_CHAR
+                    && maxlen > 1)
+            {
+                path.delete(maxlen - 1, maxlen);
+            }
+        }
+
+        return fileType;
+    }
+
+    /**
+     * Normalises the separators in a name.
+     * @param name The StringBuffer containing the name
+     * @return true if the StringBuffer was modified.
+     */
+    public static boolean fixSeparators(final StringBuffer name)
+    {
+        boolean changed = false;
+        final int maxlen = name.length();
+        for (int i = 0; i < maxlen; i++)
+        {
+            final char ch = name.charAt(i);
+            if (ch == TRANS_SEPARATOR)
+            {
+                name.setCharAt(i, SEPARATOR_CHAR);
+                changed = true;
+            }
+        }
+        return changed;
+    }
+
+    /**
+     * Extracts the scheme from a URI.
+     *
+     * @param uri The URI.
+     * @return The scheme name. Returns null if there is no scheme.
+     */
+    public static String extractScheme(final String uri)
+    {
+        return extractScheme(uri, null);
+    }
+
+    /**
+     * Extracts the scheme from a URI. Removes the scheme and ':' delimiter from
+     * the front of the URI.
+     *
+     * @param uri The URI.
+     * @param buffer Returns the remainder of the URI.
+     * @return The scheme name. Returns null if there is no scheme.
+     */
+    public static String extractScheme(final String uri, final StringBuffer buffer)
+    {
+        if (buffer != null)
+        {
+            buffer.setLength(0);
+            buffer.append(uri);
+        }
+
+        final int maxPos = uri.length();
+        for (int pos = 0; pos < maxPos; pos++)
+        {
+            final char ch = uri.charAt(pos);
+
+            if (ch == ':')
+            {
+                // Found the end of the scheme
+                final String scheme = uri.substring(0, pos);
+                if (scheme.length() <= 1 && Os.isFamily(Os.OS_FAMILY_WINDOWS))
+                {
+                    // This is not a scheme, but a Windows drive letter
+                    return null;
+                }
+                if (buffer != null)
+                {
+                    buffer.delete(0, pos + 1);
+                }
+                return scheme.intern();
+            }
+
+            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
+            {
+                // A scheme character
+                continue;
+            }
+            if (pos > 0
+                    && ((ch >= '0' && ch <= '9') || ch == '+' || ch == '-' || ch == '.'))
+            {
+                // A scheme character (these are not allowed as the first
+                // character of the scheme, but can be used as subsequent
+                // characters.
+                continue;
+            }
+
+            // Not a scheme character
+            break;
+        }
+
+        // No scheme in URI
+        return null;
+    }
+
+    /**
+     * Removes %nn encodings from a string.
+     * @param encodedStr The encoded String.
+     * @return The decoded String.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static String decode(final String encodedStr)
+            throws FileSystemException
+    {
+        if (encodedStr == null)
+        {
+            return null;
+        }
+        if (encodedStr.indexOf('%') < 0)
+        {
+            return encodedStr;
+        }
+        final StringBuffer buffer = new StringBuffer(encodedStr);
+        decode(buffer, 0, buffer.length());
+        return buffer.toString();
+    }
+
+    /**
+     * Removes %nn encodings from a string.
+     * @param buffer StringBuffer containing the string to decode.
+     * @param offset The position in the string to start decoding.
+     * @param length The number of characters to decode.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static void decode(final StringBuffer buffer, final int offset, final int length)
+            throws FileSystemException
+    {
+        int index = offset;
+        int count = length;
+        for (; count > 0; count--, index++)
+        {
+            final char ch = buffer.charAt(index);
+            if (ch != '%')
+            {
+                continue;
+            }
+            if (count < 3)
+            {
+                throw new FileSystemException(
+                        "vfs.provider/invalid-escape-sequence.error", buffer
+                                .substring(index, index + count));
+            }
+
+            // Decode
+            int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
+            int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
+            if (dig1 == -1 || dig2 == -1)
+            {
+                throw new FileSystemException(
+                        "vfs.provider/invalid-escape-sequence.error", buffer
+                                .substring(index, index + 3));
+            }
+            char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
+
+            // Replace
+            buffer.setCharAt(index, value);
+            buffer.delete(index + 1, index + 3);
+            count -= 2;
+        }
+    }
+
+    /**
+     * Encodes and appends a string to a StringBuffer.
+     * @param buffer The StringBuffer to append to.
+     * @param unencodedValue The String to encode and append.
+     * @param reserved characters to encode.
+     */
+    public static void appendEncoded(final StringBuffer buffer,
+            final String unencodedValue, final char[] reserved)
+    {
+        final int offset = buffer.length();
+        buffer.append(unencodedValue);
+        encode(buffer, offset, unencodedValue.length(), reserved);
+    }
+
+    /**
+     * Encodes a set of reserved characters in a StringBuffer, using the URI %nn
+     * encoding. Always encodes % characters.
+     * @param buffer The StringBuffer to append to.
+     * @param offset The position in the buffer to start encoding at.
+     * @param length The number of characters to encode.
+     * @param reserved characters to encode.
+     */
+    public static void encode(final StringBuffer buffer, final int offset,
+            final int length, final char[] reserved)
+    {
+        int index = offset;
+        int count = length;
+        for (; count > 0; index++, count--)
+        {
+            final char ch = buffer.charAt(index);
+            boolean match = ch == '%';
+            if (reserved != null)
+            {
+                for (int i = 0; !match && i < reserved.length; i++)
+                {
+                    if (ch == reserved[i])
+                    {
+                        match = true;
+                    }
+                }
+            }
+            if (match)
+            {
+                // Encode
+                char[] digits =
+                    {Character.forDigit(((ch >> BITS_IN_HALF_BYTE) & LOW_MASK), HEX_BASE),
+                     Character.forDigit((ch & LOW_MASK), HEX_BASE)};
+                buffer.setCharAt(index, '%');
+                buffer.insert(index + 1, digits);
+                index += 2;
+            }
+        }
+    }
+
+    /**
+     * Removes %nn encodings from a string.
+     * @param decodedStr The decoded String.
+     * @return The encoded String.
+     */
+    public static String encode(final String decodedStr)
+    {
+        return encode(decodedStr, null);
+    }
+
+    /**
+     * Converts "special" characters to their %nn value.
+     * @param decodedStr The decoded String.
+     * @param reserved Characters to encode.
+     * @return The encoded String
+     */
+    public static String encode(final String decodedStr, final char[] reserved)
+    {
+        if (decodedStr == null)
+        {
+            return null;
+        }
+        final StringBuffer buffer = new StringBuffer(decodedStr);
+        encode(buffer, 0, buffer.length(), reserved);
+        return buffer.toString();
+    }
+
+    /**
+     * Encode an array of Strings.
+     * @param strings The array of Strings to encode.
+     * @return An array of encoded Strings.
+     */
+    public static String[] encode(String[] strings)
+    {
+        if (strings == null)
+        {
+            return null;
+        }
+        for (int i = 0; i < strings.length; i++)
+        {
+            strings[i] = encode(strings[i]);
+        }
+        return strings;
+    }
+
+    /**
+     * Decodes the String.
+     * @param uri The String to decode.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static void checkUriEncoding(String uri) throws FileSystemException
+    {
+        decode(uri);
+    }
+
+    public static void canonicalizePath(StringBuffer buffer, int offset,
+            int length, FileNameParser fileNameParser)
+            throws FileSystemException
+    {
+        int index = offset;
+        int count = length;
+        for (; count > 0; count--, index++)
+        {
+            final char ch = buffer.charAt(index);
+            if (ch == '%')
+            {
+                if (count < 3)
+                {
+                    throw new FileSystemException(
+                            "vfs.provider/invalid-escape-sequence.error",
+                            buffer.substring(index, index + count));
+                }
+
+                // Decode
+                int dig1 = Character.digit(buffer.charAt(index + 1), HEX_BASE);
+                int dig2 = Character.digit(buffer.charAt(index + 2), HEX_BASE);
+                if (dig1 == -1 || dig2 == -1)
+                {
+                    throw new FileSystemException(
+                            "vfs.provider/invalid-escape-sequence.error",
+                            buffer.substring(index, index + 3));
+                }
+                char value = (char) (dig1 << BITS_IN_HALF_BYTE | dig2);
+
+                boolean match = value == '%'
+                        || (fileNameParser != null && fileNameParser.encodeCharacter(value));
+
+                if (match)
+                {
+                    // this is a reserved character, not allowed to decode
+                    index += 2;
+                    count -= 2;
+                    continue;
+                }
+
+                // Replace
+                buffer.setCharAt(index, value);
+                buffer.delete(index + 1, index + 3);
+                count -= 2;
+            }
+            else if (fileNameParser.encodeCharacter(ch))
+            {
+                // Encode
+                char[] digits =
+                    {Character.forDigit(((ch >> BITS_IN_HALF_BYTE) & LOW_MASK), HEX_BASE),
+                     Character.forDigit((ch & LOW_MASK), HEX_BASE) };
+                buffer.setCharAt(index, '%');
+                buffer.insert(index + 1, digits);
+                index += 2;
+            }
+        }
+    }
+
+    /**
+     * Extract the query String from the URI.
+     * @param name StringBuffer containing the URI.
+     * @return The query string, if any. null otherwise.
+     */
+    public static String extractQueryString(StringBuffer name)
+    {
+        for (int pos = 0; pos < name.length(); pos++)
+        {
+            if (name.charAt(pos) == '?')
+            {
+                String queryString = name.substring(pos + 1);
+                name.delete(pos, name.length());
+                return queryString;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponent.java
new file mode 100644
index 0000000..c02849e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponent.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * This interface is used to manage the lifecycle of all VFS components.
+ * This includes all implementations of the following interfaces:
+ * <ul>
+ * <li>{@link FileProvider}
+ * <li>{@link org.apache.commons.vfs.FileSystem}
+ * <li>{@link FileReplicator}
+ * <li>{@link TemporaryFileStore}
+ * </ul>
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface VfsComponent
+{
+    /**
+     * Sets the Logger to use for the component.
+     *
+     * @param logger The Log
+     */
+    void setLogger(Log logger);
+
+    /**
+     * Sets the context for the component.
+     *
+     * @param context The context.
+     */
+    void setContext(VfsComponentContext context);
+
+    /**
+     * Initialises the component.
+     * @throws FileSystemException if an error occurs.
+     */
+    void init() throws FileSystemException;
+
+    /**
+     * Closes the component.
+     */
+    void close();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponentContext.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponentContext.java
new file mode 100644
index 0000000..bfc9515
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/VfsComponentContext.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+
+import java.io.File;
+
+/**
+ * Allows VFS components to access the services they need, such as the file
+ * replicator.  A VFS component is supplied with a context as part of its
+ * initialisation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @see VfsComponent#setContext
+ */
+public interface VfsComponentContext
+{
+    /**
+     * Locate a file by name.  See
+     * {@link FileSystemManager#resolveFile(FileObject, String)} for a
+     * description of how this works.
+     * @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.
+     */
+    FileObject resolveFile(FileObject baseFile, String name, FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    /**
+     * Locate a file by name.  See
+     * {@link FileSystemManager#resolveFile( String)} for a
+     * description of how this works.
+     * @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.
+     */
+    FileObject resolveFile(String name, FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    /**
+     * Parse a URI into a FileName.
+     * @param uri The URI String.
+     * @return The FileName.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileName parseURI(String uri) throws FileSystemException;
+
+    /**
+     * Locates a file replicator for the provider to use.
+     * @return The FileReplicator.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileReplicator getReplicator() throws FileSystemException;
+
+    /**
+     * Locates a temporary file store for the provider to use.
+     * @return The TemporaryFileStore.
+     * @throws FileSystemException if an error occurs.
+     */
+    TemporaryFileStore getTemporaryFileStore() throws FileSystemException;
+
+    /**
+     * Returns a {@link FileObject} for a local file.
+     * @param file The File to convert to a FileObject.
+     * @return the FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    FileObject toFileObject(File file) throws FileSystemException;
+
+    /**
+     * Returns the filesystem manager for the current context.
+     *
+     * @return the filesystem manager
+     */
+    FileSystemManager getFileSystemManager();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/BZip2Constants.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/BZip2Constants.java
new file mode 100644
index 0000000..88e435c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/BZip2Constants.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs.provider.bzip2;
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+/**
+ * Base class for both the compress and decompress classes. Holds common arrays,
+ * and static data.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+interface BZip2Constants
+{
+    int BASE_BLOCK_SIZE = 100000;
+    int MAX_ALPHA_SIZE = 258;
+    int MAX_CODE_LEN = 23;
+    int RUNA = 0;
+    int RUNB = 1;
+    int N_GROUPS = 6;
+    int G_SIZE = 50;
+    int N_ITERS = 4;
+    int MAX_SELECTORS = (2 + (900000 / G_SIZE));
+    int NUM_OVERSHOOT_BYTES = 20;
+
+    int[] RAND_NUMS = new int[]
+    {
+        619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+        985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+        733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+        419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+        878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+        862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+        150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+        170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+        73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+        909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+        641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+        161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+        382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+        98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+        227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+        469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+        184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+        715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+        951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+        652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+        645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+        609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+        653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+        411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+        170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+        857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+        669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+        944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+        344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+        897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+        433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+        686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+        946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+        978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+        680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+        707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+        297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+        134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+        343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+        140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+        170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+        369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+        804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+        896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+        661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+        768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+        61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+        372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+        780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+        920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+        645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+        936, 638
+    };
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileObject.java
new file mode 100644
index 0000000..dcad982
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileObject.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+//TODO: Revert to [compress]
+//import org.apache.commons.compress.bzip2.CBZip2InputStream;
+//import org.apache.commons.compress.bzip2.CBZip2OutputStream;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileObject;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileSystem;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * the bzip2 file.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class Bzip2FileObject extends CompressedFileFileObject
+{
+    protected Bzip2FileObject(FileName name, FileObject container, CompressedFileFileSystem fs)
+    {
+        super(name, container, fs);
+    }
+
+    protected InputStream doGetInputStream() throws Exception
+    {
+        // check file
+        InputStream is = getContainer().getContent().getInputStream();
+        return wrapInputStream(getName().getURI(), is);
+    }
+
+    public static InputStream wrapInputStream(final String name, final InputStream is) throws IOException
+    {
+        final int b1 = is.read();
+        final int b2 = is.read();
+        if (b1 != 'B' || b2 != 'Z')
+        {
+            throw new FileSystemException("vfs.provider.compressedFile/not-a-compressedFile-file.error", name);
+        }
+        return new CBZip2InputStream(is);
+    }
+
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        OutputStream os = getContainer().getContent().getOutputStream(false);
+        os.write('B');
+        os.write('Z');
+
+        return new CBZip2OutputStream(os);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileProvider.java
new file mode 100644
index 0000000..0a1d33f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileProvider;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Provides access to the content of bzip2 compressed files.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class Bzip2FileProvider extends CompressedFileFileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities =
+            Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+                    {
+                            Capability.GET_LAST_MODIFIED,
+                            Capability.GET_TYPE,
+                            Capability.LIST_CHILDREN,
+                            Capability.READ_CONTENT,
+                            Capability.WRITE_CONTENT,
+                            Capability.URI,
+                            Capability.COMPRESS
+                    }));
+
+    public Bzip2FileProvider()
+    {
+        super();
+    }
+
+    protected FileSystem createFileSystem(FileName name, FileObject file,
+                                          FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        return new Bzip2FileSystem(name, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileSystem.java
new file mode 100644
index 0000000..e7f51ec
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/Bzip2FileSystem.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileSystem;
+
+import java.util.Collection;
+
+/**
+ * Filesytem to handle compressed files using the bzip2 method.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class Bzip2FileSystem extends CompressedFileFileSystem
+{
+    protected Bzip2FileSystem(FileName rootName, FileObject parentLayer, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+    }
+
+    protected FileObject createFile(FileName name) throws FileSystemException
+    {
+        return new Bzip2FileObject(name, getParentLayer(), this);
+    }
+
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(Bzip2FileProvider.capabilities);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2InputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2InputStream.java
new file mode 100644
index 0000000..2ad6661
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2InputStream.java
@@ -0,0 +1,995 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+/**
+ * An input stream that decompresses from the BZip2 format (without the file
+ * header chars) to be read as any other stream.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+class CBZip2InputStream
+        extends InputStream
+        implements BZip2Constants
+{
+    private static final int START_BLOCK_STATE = 1;
+    private static final int RAND_PART_A_STATE = 2;
+    private static final int RAND_PART_B_STATE = 3;
+    private static final int RAND_PART_C_STATE = 4;
+    private static final int NO_RAND_PART_A_STATE = 5;
+    private static final int NO_RAND_PART_B_STATE = 6;
+    private static final int NO_RAND_PART_C_STATE = 7;
+
+    private CRC crc = new CRC();
+    private boolean[] inUse = new boolean[256];
+    private char[] seqToUnseq = new char[256];
+    private char[] unseqToSeq = new char[256];
+    private char[] selector = new char[MAX_SELECTORS];
+    private char[] selectorMtf = new char[MAX_SELECTORS];
+
+    /*
+     * freq table collected to save a pass over the data
+     * during decompression.
+     */
+    private int[] unzftab = new int[256];
+
+    private int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];
+    private int[][] base = new int[N_GROUPS][MAX_ALPHA_SIZE];
+    private int[][] perm = new int[N_GROUPS][MAX_ALPHA_SIZE];
+    private int[] minLens = new int[N_GROUPS];
+
+    private boolean streamEnd;
+    private int currentChar = -1;
+
+    private int currentState = START_BLOCK_STATE;
+    private int rNToGo;
+    private int rTPos;
+    private int tPos;
+
+    private int i2;
+    private int count;
+    private int chPrev;
+    private int ch2;
+    private int j2;
+    private char z;
+
+    private boolean m_blockRandomised;
+
+    /*
+     * always: in the range 0 .. 9.
+     * The current block size is 100000 * this number.
+     */
+    private int blockSize100k;
+    private int bsBuff;
+    private int bsLive;
+
+    private InputStream m_input;
+
+    private int computedBlockCRC;
+    private int computedCombinedCRC;
+
+    /*
+     * index of the last char in the block, so
+     * the block size == last + 1.
+     */
+    private int last;
+    private char[] mll8;
+    private int nInUse;
+
+    /*
+     * index in zptr[] of original string after sorting.
+     */
+    private int origPtr;
+
+    private int storedBlockCRC;
+    private int storedCombinedCRC;
+    private int[] tt;
+
+    CBZip2InputStream(final InputStream input)
+    {
+        bsSetStream(input);
+        initialize();
+        initBlock();
+        setupBlock();
+    }
+
+    private static void badBlockHeader()
+    {
+        cadvise();
+    }
+
+    private static void blockOverrun()
+    {
+        cadvise();
+    }
+
+    private static void cadvise()
+    {
+        System.out.println("CRC Error");
+        //throw new CCoruptionError();
+    }
+
+    private static void compressedStreamEOF()
+    {
+        cadvise();
+    }
+
+    private static void crcError()
+    {
+        cadvise();
+    }
+
+    /**
+     * a fake <code>available</code> which always returns 1 as long as the stream is not at end.
+     * This is required to make this stream work if wrapped in an BufferedInputStream.
+     *
+     */
+    public int available() throws IOException
+    {
+        if (!streamEnd)
+        {
+            return 1;
+        }
+        return 0;
+    }
+
+    public int read()
+    {
+        if (streamEnd)
+        {
+            return -1;
+        }
+        else
+        {
+            int retChar = currentChar;
+            switch (currentState)
+            {
+                case START_BLOCK_STATE:
+                    break;
+                case RAND_PART_A_STATE:
+                    break;
+                case RAND_PART_B_STATE:
+                    setupRandPartB();
+                    break;
+                case RAND_PART_C_STATE:
+                    setupRandPartC();
+                    break;
+                case NO_RAND_PART_A_STATE:
+                    break;
+                case NO_RAND_PART_B_STATE:
+                    setupNoRandPartB();
+                    break;
+                case NO_RAND_PART_C_STATE:
+                    setupNoRandPartC();
+                    break;
+                default:
+                    break;
+            }
+            return retChar;
+        }
+    }
+
+    private void setDecompressStructureSizes(int newSize100k)
+    {
+        if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k
+                && blockSize100k <= 9))
+        {
+            // throw new IOException("Invalid block size");
+        }
+
+        blockSize100k = newSize100k;
+
+        if (newSize100k == 0)
+        {
+            return;
+        }
+
+        int n = BASE_BLOCK_SIZE * newSize100k;
+        mll8 = new char[n];
+        tt = new int[n];
+    }
+
+    private void setupBlock()
+    {
+        int[] cftab = new int[257];
+        char ch;
+
+        cftab[0] = 0;
+        for (int i = 1; i <= 256; i++)
+        {
+            cftab[i] = unzftab[i - 1];
+        }
+        for (int i = 1; i <= 256; i++)
+        {
+            cftab[i] += cftab[i - 1];
+        }
+
+        for (int i = 0; i <= last; i++)
+        {
+            ch = mll8[i];
+            tt[cftab[ch]] = i;
+            cftab[ch]++;
+        }
+        cftab = null;
+
+        tPos = tt[origPtr];
+
+        count = 0;
+        i2 = 0;
+        ch2 = 256;
+        /*
+         * not a char and not EOF
+         */
+        if (m_blockRandomised)
+        {
+            rNToGo = 0;
+            rTPos = 0;
+            setupRandPartA();
+        }
+        else
+        {
+            setupNoRandPartA();
+        }
+    }
+
+    private void setupNoRandPartA()
+    {
+        if (i2 <= last)
+        {
+            chPrev = ch2;
+            ch2 = mll8[tPos];
+            tPos = tt[tPos];
+            i2++;
+
+            currentChar = ch2;
+            currentState = NO_RAND_PART_B_STATE;
+            crc.updateCRC(ch2);
+        }
+        else
+        {
+            endBlock();
+            initBlock();
+            setupBlock();
+        }
+    }
+
+    private void setupNoRandPartB()
+    {
+        if (ch2 != chPrev)
+        {
+            currentState = NO_RAND_PART_A_STATE;
+            count = 1;
+            setupNoRandPartA();
+        }
+        else
+        {
+            count++;
+            if (count >= 4)
+            {
+                z = mll8[tPos];
+                tPos = tt[tPos];
+                currentState = NO_RAND_PART_C_STATE;
+                j2 = 0;
+                setupNoRandPartC();
+            }
+            else
+            {
+                currentState = NO_RAND_PART_A_STATE;
+                setupNoRandPartA();
+            }
+        }
+    }
+
+    private void setupNoRandPartC()
+    {
+        if (j2 < z)
+        {
+            currentChar = ch2;
+            crc.updateCRC(ch2);
+            j2++;
+        }
+        else
+        {
+            currentState = NO_RAND_PART_A_STATE;
+            i2++;
+            count = 0;
+            setupNoRandPartA();
+        }
+    }
+
+    private void setupRandPartA()
+    {
+        if (i2 <= last)
+        {
+            chPrev = ch2;
+            ch2 = mll8[tPos];
+            tPos = tt[tPos];
+            if (rNToGo == 0)
+            {
+                rNToGo = RAND_NUMS[rTPos];
+                rTPos++;
+                if (rTPos == 512)
+                {
+                    rTPos = 0;
+                }
+            }
+            rNToGo--;
+            ch2 ^= ((rNToGo == 1) ? 1 : 0);
+            i2++;
+
+            currentChar = ch2;
+            currentState = RAND_PART_B_STATE;
+            crc.updateCRC(ch2);
+        }
+        else
+        {
+            endBlock();
+            initBlock();
+            setupBlock();
+        }
+    }
+
+    private void setupRandPartB()
+    {
+        if (ch2 != chPrev)
+        {
+            currentState = RAND_PART_A_STATE;
+            count = 1;
+            setupRandPartA();
+        }
+        else
+        {
+            count++;
+            if (count >= 4)
+            {
+                z = mll8[tPos];
+                tPos = tt[tPos];
+                if (rNToGo == 0)
+                {
+                    rNToGo = RAND_NUMS[rTPos];
+                    rTPos++;
+                    if (rTPos == 512)
+                    {
+                        rTPos = 0;
+                    }
+                }
+                rNToGo--;
+                z ^= ((rNToGo == 1) ? 1 : 0);
+                j2 = 0;
+                currentState = RAND_PART_C_STATE;
+                setupRandPartC();
+            }
+            else
+            {
+                currentState = RAND_PART_A_STATE;
+                setupRandPartA();
+            }
+        }
+    }
+
+    private void setupRandPartC()
+    {
+        if (j2 < z)
+        {
+            currentChar = ch2;
+            crc.updateCRC(ch2);
+            j2++;
+        }
+        else
+        {
+            currentState = RAND_PART_A_STATE;
+            i2++;
+            count = 0;
+            setupRandPartA();
+        }
+    }
+
+    private void getAndMoveToFrontDecode()
+    {
+        int nextSym;
+
+        int limitLast = BASE_BLOCK_SIZE * blockSize100k;
+        origPtr = readVariableSizedInt(24);
+
+        recvDecodingTables();
+        int EOB = nInUse + 1;
+        int groupNo = -1;
+        int groupPos = 0;
+
+        /*
+         * Setting up the unzftab entries here is not strictly
+         * necessary, but it does save having to do it later
+         * in a separate pass, and so saves a block's worth of
+         * cache misses.
+         */
+        for (int i = 0; i <= 255; i++)
+        {
+            unzftab[i] = 0;
+        }
+
+        final char[] yy = new char[256];
+        for (int i = 0; i <= 255; i++)
+        {
+            yy[i] = (char) i;
+        }
+
+        last = -1;
+        int zt;
+        int zn;
+        int zvec;
+        int zj;
+        groupNo++;
+        groupPos = G_SIZE - 1;
+
+        zt = selector[groupNo];
+        zn = minLens[zt];
+        zvec = bsR(zn);
+        while (zvec > limit[zt][zn])
+        {
+            zn++;
+
+            while (bsLive < 1)
+            {
+                int zzi = 0;
+                try
+                {
+                    zzi = m_input.read();
+                }
+                catch (IOException e)
+                {
+                    compressedStreamEOF();
+                }
+                if (zzi == -1)
+                {
+                    compressedStreamEOF();
+                }
+                bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                bsLive += 8;
+            }
+
+            zj = (bsBuff >> (bsLive - 1)) & 1;
+            bsLive--;
+
+            zvec = (zvec << 1) | zj;
+        }
+        nextSym = perm[zt][zvec - base[zt][zn]];
+
+        while (true)
+        {
+            if (nextSym == EOB)
+            {
+                break;
+            }
+
+            if (nextSym == RUNA || nextSym == RUNB)
+            {
+                char ch;
+                int s = -1;
+                int N = 1;
+                do
+                {
+                    if (nextSym == RUNA)
+                    {
+                        s = s + (0 + 1) * N;
+                    }
+                    else // if( nextSym == RUNB )
+                    {
+                        s = s + (1 + 1) * N;
+                    }
+                    N = N * 2;
+
+                    if (groupPos == 0)
+                    {
+                        groupNo++;
+                        groupPos = G_SIZE;
+                    }
+                    groupPos--;
+                    zt = selector[groupNo];
+                    zn = minLens[zt];
+                    zvec = bsR(zn);
+                    while (zvec > limit[zt][zn])
+                    {
+                        zn++;
+
+                        while (bsLive < 1)
+                        {
+                            int zzi = 0;
+                            try
+                            {
+                                zzi = m_input.read();
+                            }
+                            catch (IOException e)
+                            {
+                                compressedStreamEOF();
+                            }
+                            if (zzi == -1)
+                            {
+                                compressedStreamEOF();
+                            }
+                            bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                            bsLive += 8;
+                        }
+
+                        zj = (bsBuff >> (bsLive - 1)) & 1;
+                        bsLive--;
+                        zvec = (zvec << 1) | zj;
+                    }
+
+                    nextSym = perm[zt][zvec - base[zt][zn]];
+
+                }
+                while (nextSym == RUNA || nextSym == RUNB);
+
+                s++;
+                ch = seqToUnseq[yy[0]];
+                unzftab[ch] += s;
+
+                while (s > 0)
+                {
+                    last++;
+                    mll8[last] = ch;
+                    s--;
+                }
+
+                if (last >= limitLast)
+                {
+                    blockOverrun();
+                }
+                continue;
+            }
+            else
+            {
+                char tmp;
+                last++;
+                if (last >= limitLast)
+                {
+                    blockOverrun();
+                }
+
+                tmp = yy[nextSym - 1];
+                unzftab[seqToUnseq[tmp]]++;
+                mll8[last] = seqToUnseq[tmp];
+
+                /*
+                 * This loop is hammered during decompression,
+                 * hence the unrolling.
+                 * for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
+                 */
+                int j = nextSym - 1;
+                for (; j > 3; j -= 4)
+                {
+                    yy[j] = yy[j - 1];
+                    yy[j - 1] = yy[j - 2];
+                    yy[j - 2] = yy[j - 3];
+                    yy[j - 3] = yy[j - 4];
+                }
+                for (; j > 0; j--)
+                {
+                    yy[j] = yy[j - 1];
+                }
+
+                yy[0] = tmp;
+
+                if (groupPos == 0)
+                {
+                    groupNo++;
+                    groupPos = G_SIZE;
+                }
+                groupPos--;
+                zt = selector[groupNo];
+                zn = minLens[zt];
+                zvec = bsR(zn);
+                while (zvec > limit[zt][zn])
+                {
+                    zn++;
+
+                    while (bsLive < 1)
+                    {
+                        char ch = 0;
+                        try
+                        {
+                            ch = (char) m_input.read();
+                        }
+                        catch (IOException e)
+                        {
+                            compressedStreamEOF();
+                        }
+
+                        bsBuff = (bsBuff << 8) | (ch & 0xff);
+                        bsLive += 8;
+                    }
+
+                    zj = (bsBuff >> (bsLive - 1)) & 1;
+                    bsLive--;
+
+                    zvec = (zvec << 1) | zj;
+                }
+                nextSym = perm[zt][zvec - base[zt][zn]];
+
+                continue;
+            }
+        }
+    }
+
+    private void bsFinishedWithStream()
+    {
+        if (m_input != null)
+        {
+            try
+            {
+                m_input.close();
+            }
+            catch (IOException e)
+            {
+                // Ignore the exception.
+            }
+        }
+        m_input = null;
+    }
+
+    private int readVariableSizedInt(final int numBits)
+    {
+        return bsR(numBits);
+    }
+
+    private char readUnsignedChar()
+    {
+        return (char) bsR(8);
+    }
+
+    private int readInt()
+    {
+        int u = 0;
+        u = (u << 8) | bsR(8);
+        u = (u << 8) | bsR(8);
+        u = (u << 8) | bsR(8);
+        u = (u << 8) | bsR(8);
+        return u;
+    }
+
+    private int bsR(final int n)
+    {
+        while (bsLive < n)
+        {
+            int ch = 0;
+            try
+            {
+                ch = m_input.read();
+            }
+            catch (final IOException ioe)
+            {
+                compressedStreamEOF();
+            }
+
+            if (ch == -1)
+            {
+                compressedStreamEOF();
+            }
+
+            bsBuff = (bsBuff << 8) | (ch & 0xff);
+            bsLive += 8;
+        }
+
+        final int result = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
+        bsLive -= n;
+        return result;
+    }
+
+    private void bsSetStream(final InputStream input)
+    {
+        m_input = input;
+        bsLive = 0;
+        bsBuff = 0;
+    }
+
+    private void complete()
+    {
+        storedCombinedCRC = readInt();
+        if (storedCombinedCRC != computedCombinedCRC)
+        {
+            crcError();
+        }
+
+        bsFinishedWithStream();
+        streamEnd = true;
+    }
+
+    private void endBlock()
+    {
+        computedBlockCRC = crc.getFinalCRC();
+        /*
+         * A bad CRC is considered a fatal error.
+         */
+        if (storedBlockCRC != computedBlockCRC)
+        {
+            crcError();
+        }
+
+        computedCombinedCRC = (computedCombinedCRC << 1)
+                | (computedCombinedCRC >>> 31);
+        computedCombinedCRC ^= computedBlockCRC;
+    }
+
+    private void hbCreateDecodeTables(final int[] limit,
+                                      final int[] base,
+                                      final int[] perm,
+                                      final char[] length,
+                                      final int minLen,
+                                      final int maxLen,
+                                      final int alphaSize)
+    {
+        int pp = 0;
+        for (int i = minLen; i <= maxLen; i++)
+        {
+            for (int j = 0; j < alphaSize; j++)
+            {
+                if (length[j] == i)
+                {
+                    perm[pp] = j;
+                    pp++;
+                }
+            }
+        }
+
+        for (int i = 0; i < MAX_CODE_LEN; i++)
+        {
+            base[i] = 0;
+        }
+
+        for (int i = 0; i < alphaSize; i++)
+        {
+            base[length[i] + 1]++;
+        }
+
+        for (int i = 1; i < MAX_CODE_LEN; i++)
+        {
+            base[i] += base[i - 1];
+        }
+
+        for (int i = 0; i < MAX_CODE_LEN; i++)
+        {
+            limit[i] = 0;
+        }
+
+        int vec = 0;
+        for (int i = minLen; i <= maxLen; i++)
+        {
+            vec += (base[i + 1] - base[i]);
+            limit[i] = vec - 1;
+            vec <<= 1;
+        }
+
+        for (int i = minLen + 1; i <= maxLen; i++)
+        {
+            base[i] = ((limit[i - 1] + 1) << 1) - base[i];
+        }
+    }
+
+    private void initBlock()
+    {
+        final char magic1 = readUnsignedChar();
+        final char magic2 = readUnsignedChar();
+        final char magic3 = readUnsignedChar();
+        final char magic4 = readUnsignedChar();
+        final char magic5 = readUnsignedChar();
+        final char magic6 = readUnsignedChar();
+        if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45 &&
+                magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90)
+        {
+            complete();
+            return;
+        }
+
+        if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59 ||
+                magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59)
+        {
+            badBlockHeader();
+            streamEnd = true;
+            return;
+        }
+
+        storedBlockCRC = readInt();
+
+        if (bsR(1) == 1)
+        {
+            m_blockRandomised = true;
+        }
+        else
+        {
+            m_blockRandomised = false;
+        }
+
+        //        currBlockNo++;
+        getAndMoveToFrontDecode();
+
+        crc.initialiseCRC();
+        currentState = START_BLOCK_STATE;
+    }
+
+    private void initialize()
+    {
+        final char magic3 = readUnsignedChar();
+        final char magic4 = readUnsignedChar();
+        if (magic3 != 'h' || magic4 < '1' || magic4 > '9')
+        {
+            bsFinishedWithStream();
+            streamEnd = true;
+            return;
+        }
+
+        setDecompressStructureSizes(magic4 - '0');
+        computedCombinedCRC = 0;
+    }
+
+    private void makeMaps()
+    {
+        nInUse = 0;
+        for (int i = 0; i < 256; i++)
+        {
+            if (inUse[i])
+            {
+                seqToUnseq[nInUse] = (char) i;
+                unseqToSeq[i] = (char) nInUse;
+                nInUse++;
+            }
+        }
+    }
+
+    private void recvDecodingTables()
+    {
+        buildInUseTable();
+        makeMaps();
+        final int alphaSize = nInUse + 2;
+
+        /*
+         * Now the selectors
+         */
+        final int groupCount = bsR(3);
+        final int selectorCount = bsR(15);
+        for (int i = 0; i < selectorCount; i++)
+        {
+            int run = 0;
+            while (bsR(1) == 1)
+            {
+                run++;
+            }
+            selectorMtf[i] = (char) run;
+        }
+
+        /*
+         * Undo the MTF values for the selectors.
+         */
+        final char[] pos = new char[N_GROUPS];
+        for (char v = 0; v < groupCount; v++)
+        {
+            pos[v] = v;
+        }
+
+        for (int i = 0; i < selectorCount; i++)
+        {
+            int v = selectorMtf[i];
+            final char tmp = pos[v];
+            while (v > 0)
+            {
+                pos[v] = pos[v - 1];
+                v--;
+            }
+            pos[0] = tmp;
+            selector[i] = tmp;
+        }
+
+        final char[][] len = new char[N_GROUPS][MAX_ALPHA_SIZE];
+        /*
+         * Now the coding tables
+         */
+        for (int i = 0; i < groupCount; i++)
+        {
+            int curr = bsR(5);
+            for (int j = 0; j < alphaSize; j++)
+            {
+                while (bsR(1) == 1)
+                {
+                    if (bsR(1) == 0)
+                    {
+                        curr++;
+                    }
+                    else
+                    {
+                        curr--;
+                    }
+                }
+                len[i][j] = (char) curr;
+            }
+        }
+
+        /*
+         * Create the Huffman decoding tables
+         */
+        for (int k = 0; k < groupCount; k++)
+        {
+            int minLen = 32;
+            int maxLen = 0;
+            for (int i = 0; i < alphaSize; i++)
+            {
+                if (len[k][i] > maxLen)
+                {
+                    maxLen = len[k][i];
+                }
+                if (len[k][i] < minLen)
+                {
+                    minLen = len[k][i];
+                }
+            }
+            hbCreateDecodeTables(limit[k], base[k], perm[k], len[k], minLen,
+                    maxLen, alphaSize);
+            minLens[k] = minLen;
+        }
+    }
+
+    private void buildInUseTable()
+    {
+        final boolean[] inUse16 = new boolean[16];
+
+        /*
+         * Receive the mapping table
+         */
+        for (int i = 0; i < 16; i++)
+        {
+            if (bsR(1) == 1)
+            {
+                inUse16[i] = true;
+            }
+            else
+            {
+                inUse16[i] = false;
+            }
+        }
+
+        for (int i = 0; i < 256; i++)
+        {
+            inUse[i] = false;
+        }
+
+        for (int i = 0; i < 16; i++)
+        {
+            if (inUse16[i])
+            {
+                for (int j = 0; j < 16; j++)
+                {
+                    if (bsR(1) == 1)
+                    {
+                        inUse[i * 16 + j] = true;
+                    }
+                }
+            }
+        }
+    }
+
+    public void close() throws IOException
+    {
+        bsFinishedWithStream();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2OutputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2OutputStream.java
new file mode 100644
index 0000000..a3fee90
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CBZip2OutputStream.java
@@ -0,0 +1,2037 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+/**
+ * An output stream that compresses into the BZip2 format (without the file
+ * header chars) into another stream. TODO: Update to BZip2 1.0.1
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+class CBZip2OutputStream
+        extends OutputStream
+        implements BZip2Constants
+{
+    private static final int LOWER_BYTE_MASK = 0x000000ff;
+    private static final int UPPER_BYTE_MASK = 0xffffff00;
+    private static final int SETMASK = (1 << 21);
+    private static final int CLEARMASK = (~SETMASK);
+    private static final int GREATER_ICOST = 15;
+    private static final int LESSER_ICOST = 0;
+    private static final int SMALL_THRESH = 20;
+    private static final int DEPTH_THRESH = 10;
+
+    /*
+     * If you are ever unlucky/improbable enough
+     * to get a stack overflow whilst sorting,
+     * increase the following constant and try
+     * again.  In practice I have never seen the
+     * stack go above 27 elems, so the following
+     * limit seems very generous.
+     */
+    private static final int QSORT_STACK_SIZE = 1000;
+
+    private CRC crc = new CRC();
+
+    private boolean[] inUse = new boolean[256];
+
+    private char[] seqToUnseq = new char[256];
+    private char[] unseqToSeq = new char[256];
+
+    private char[] selector = new char[MAX_SELECTORS];
+    private char[] selectorMtf = new char[MAX_SELECTORS];
+
+    private int[] mtfFreq = new int[MAX_ALPHA_SIZE];
+
+    private int currentChar = -1;
+    private int runLength;
+
+    private boolean closed;
+
+    /*
+     * Knuth's increments seem to work better
+     * than Incerpi-Sedgewick here.  Possibly
+     * because the number of elems to sort is
+     * usually small, typically <= 20.
+     */
+    private int[] incs = new int[]
+            {
+                    1, 4, 13, 40, 121, 364, 1093, 3280,
+                    9841, 29524, 88573, 265720,
+                    797161, 2391484
+            };
+
+    private boolean blockRandomised;
+
+    /*
+     * always: in the range 0 .. 9.
+     * The current block size is 100000 * this number.
+     */
+    private int blockSize100k;
+    private int bsBuff;
+    private int bsLive;
+
+    /*
+     * index of the last char in the block, so
+     * the block size == last + 1.
+     */
+    private int last;
+
+    /*
+     * index in zptr[] of original string after sorting.
+     */
+    private int origPtr;
+
+    private int allowableBlockSize;
+
+    private char[] block;
+
+    private int blockCRC;
+    private int combinedCRC;
+
+    private OutputStream bsStream;
+    private boolean firstAttempt;
+    private int[] ftab;
+    private int nInUse;
+
+    private int nMTF;
+    private int[] quadrant;
+    private short[] szptr;
+    private int workDone;
+
+    /*
+     * Used when sorting.  If too many long comparisons
+     * happen, we stop sorting, randomise the block
+     * slightly, and try again.
+     */
+    private int workFactor;
+    private int workLimit;
+    private int[] zptr;
+
+    CBZip2OutputStream(final OutputStream output)
+            throws IOException
+    {
+        this(output, 9);
+    }
+
+    CBZip2OutputStream(final OutputStream output, final int blockSize)
+            throws IOException
+    {
+        bsSetStream(output);
+        workFactor = 50;
+
+        int outBlockSize = blockSize;
+        if (outBlockSize > 9)
+        {
+            outBlockSize = 9;
+        }
+        if (outBlockSize < 1)
+        {
+            outBlockSize = 1;
+        }
+        blockSize100k = outBlockSize;
+        allocateCompressStructures();
+        initialize();
+        initBlock();
+    }
+
+    private static void hbMakeCodeLengths(char[] len, int[] freq,
+                                          int alphaSize, int maxLen)
+    {
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int nNodes;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int nHeap;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int n1;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int n2;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int i;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int j;
+        /*
+         * Nodes and heap entries run from 1.  Entry 0
+         * for both the heap and nodes is a sentinel.
+         */
+        int k;
+        boolean tooLong;
+
+        int[] heap = new int[MAX_ALPHA_SIZE + 2];
+        int[] weights = new int[MAX_ALPHA_SIZE * 2];
+        int[] parent = new int[MAX_ALPHA_SIZE * 2];
+
+        for (i = 0; i < alphaSize; i++)
+        {
+            weights[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+        }
+
+        while (true)
+        {
+            nNodes = alphaSize;
+            nHeap = 0;
+
+            heap[0] = 0;
+            weights[0] = 0;
+            parent[0] = -2;
+
+            for (i = 1; i <= alphaSize; i++)
+            {
+                parent[i] = -1;
+                nHeap++;
+                heap[nHeap] = i;
+                {
+                    int zz;
+                    int tmp;
+                    zz = nHeap;
+                    tmp = heap[zz];
+                    while (weights[tmp] < weights[heap[zz >> 1]])
+                    {
+                        heap[zz] = heap[zz >> 1];
+                        zz >>= 1;
+                    }
+                    heap[zz] = tmp;
+                }
+            }
+            if (!(nHeap < (MAX_ALPHA_SIZE + 2)))
+            {
+                panic();
+            }
+
+            while (nHeap > 1)
+            {
+                n1 = heap[1];
+                heap[1] = heap[nHeap];
+                nHeap--;
+                {
+                    int zz = 0;
+                    int yy = 0;
+                    int tmp = 0;
+                    zz = 1;
+                    tmp = heap[zz];
+                    while (true)
+                    {
+                        yy = zz << 1;
+                        if (yy > nHeap)
+                        {
+                            break;
+                        }
+                        if (yy < nHeap &&
+                                weights[heap[yy + 1]] < weights[heap[yy]])
+                        {
+                            yy++;
+                        }
+                        if (weights[tmp] < weights[heap[yy]])
+                        {
+                            break;
+                        }
+                        heap[zz] = heap[yy];
+                        zz = yy;
+                    }
+                    heap[zz] = tmp;
+                }
+                n2 = heap[1];
+                heap[1] = heap[nHeap];
+                nHeap--;
+                {
+                    int zz = 0;
+                    int yy = 0;
+                    int tmp = 0;
+                    zz = 1;
+                    tmp = heap[zz];
+                    while (true)
+                    {
+                        yy = zz << 1;
+                        if (yy > nHeap)
+                        {
+                            break;
+                        }
+                        if (yy < nHeap &&
+                                weights[heap[yy + 1]] < weights[heap[yy]])
+                        {
+                            yy++;
+                        }
+                        if (weights[tmp] < weights[heap[yy]])
+                        {
+                            break;
+                        }
+                        heap[zz] = heap[yy];
+                        zz = yy;
+                    }
+                    heap[zz] = tmp;
+                }
+                nNodes++;
+                parent[n1] = nNodes;
+                parent[n2] = nNodes;
+
+                final int v1 = weights[n1];
+                final int v2 = weights[n2];
+                final int weight = calculateWeight(v1, v2);
+                weights[nNodes] = weight;
+
+                parent[nNodes] = -1;
+                nHeap++;
+                heap[nHeap] = nNodes;
+                {
+                    int zz = 0;
+                    int tmp = 0;
+                    zz = nHeap;
+                    tmp = heap[zz];
+                    while (weights[tmp] < weights[heap[zz >> 1]])
+                    {
+                        heap[zz] = heap[zz >> 1];
+                        zz >>= 1;
+                    }
+                    heap[zz] = tmp;
+                }
+            }
+            if (!(nNodes < (MAX_ALPHA_SIZE * 2)))
+            {
+                panic();
+            }
+
+            tooLong = false;
+            for (i = 1; i <= alphaSize; i++)
+            {
+                j = 0;
+                k = i;
+                while (parent[k] >= 0)
+                {
+                    k = parent[k];
+                    j++;
+                }
+                len[i - 1] = (char) j;
+                if (j > maxLen)
+                {
+                    tooLong = true;
+                }
+            }
+
+            if (!tooLong)
+            {
+                break;
+            }
+
+            for (i = 1; i < alphaSize; i++)
+            {
+                j = weights[i] >> 8;
+                j = 1 + (j / 2);
+                weights[i] = j << 8;
+            }
+        }
+    }
+
+    private static int calculateWeight(final int v1, final int v2)
+    {
+        final int upper = (v1 & UPPER_BYTE_MASK) + (v2 & UPPER_BYTE_MASK);
+        final int v1Lower = (v1 & LOWER_BYTE_MASK);
+        final int v2Lower = (v2 & LOWER_BYTE_MASK);
+        final int nnnn = (v1Lower > v2Lower) ? v1Lower : v2Lower;
+        return upper | (1 + nnnn);
+    }
+
+    private static void panic()
+    {
+        System.out.println("panic");
+        //throw new CError();
+    }
+
+    public void close()
+            throws IOException
+    {
+        if (closed)
+        {
+            return;
+        }
+
+        if (runLength > 0)
+        {
+            writeRun();
+        }
+        currentChar = -1;
+        endBlock();
+        endCompression();
+        closed = true;
+        super.close();
+        bsStream.close();
+    }
+
+    public void finalize()
+            throws Throwable
+    {
+        close();
+    }
+
+    public void flush()
+            throws IOException
+    {
+        super.flush();
+        bsStream.flush();
+    }
+
+    /**
+     * modified by Oliver Merkel, 010128
+     *
+     * @param bv Description of Parameter
+     * @throws java.io.IOException Description of Exception
+     */
+    public void write(int bv)
+            throws IOException
+    {
+        int b = (256 + bv) % 256;
+        if (currentChar != -1)
+        {
+            if (currentChar == b)
+            {
+                runLength++;
+                if (runLength > 254)
+                {
+                    writeRun();
+                    currentChar = -1;
+                    runLength = 0;
+                }
+            }
+            else
+            {
+                writeRun();
+                runLength = 1;
+                currentChar = b;
+            }
+        }
+        else
+        {
+            currentChar = b;
+            runLength++;
+        }
+    }
+
+    private void allocateCompressStructures()
+    {
+        int n = BASE_BLOCK_SIZE * blockSize100k;
+        block = new char[(n + 1 + NUM_OVERSHOOT_BYTES)];
+        quadrant = new int[(n + NUM_OVERSHOOT_BYTES)];
+        zptr = new int[n];
+        ftab = new int[65537];
+
+        if (block == null || quadrant == null || zptr == null
+                || ftab == null)
+        {
+            //int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537;
+            //compressOutOfMemory ( totalDraw, n );
+        }
+
+        /*
+         * The back end needs a place to store the MTF values
+         * whilst it calculates the coding tables.  We could
+         * put them in the zptr array.  However, these values
+         * will fit in a short, so we overlay szptr at the
+         * start of zptr, in the hope of reducing the number
+         * of cache misses induced by the multiple traversals
+         * of the MTF values when calculating coding tables.
+         * Seems to improve compression speed by about 1%.
+         */
+        //    szptr = zptr;
+
+        szptr = new short[2 * n];
+    }
+
+    private void bsFinishedWithStream()
+            throws IOException
+    {
+        while (bsLive > 0)
+        {
+            int ch = (bsBuff >> 24);
+            try
+            {
+                bsStream.write(ch);// write 8-bit
+            }
+            catch (IOException e)
+            {
+                throw e;
+            }
+            bsBuff <<= 8;
+            bsLive -= 8;
+        }
+    }
+
+    private void bsPutIntVS(int numBits, int c)
+            throws IOException
+    {
+        bsW(numBits, c);
+    }
+
+    private void bsPutUChar(int c)
+            throws IOException
+    {
+        bsW(8, c);
+    }
+
+    private void bsPutint(int u)
+            throws IOException
+    {
+        bsW(8, (u >> 24) & 0xff);
+        bsW(8, (u >> 16) & 0xff);
+        bsW(8, (u >> 8) & 0xff);
+        bsW(8, u & 0xff);
+    }
+
+    private void bsSetStream(OutputStream f)
+    {
+        bsStream = f;
+        bsLive = 0;
+        bsBuff = 0;
+    }
+
+    private void bsW(int n, int v)
+            throws IOException
+    {
+        while (bsLive >= 8)
+        {
+            int ch = (bsBuff >> 24);
+            try
+            {
+                bsStream.write(ch);// write 8-bit
+            }
+            catch (IOException e)
+            {
+                throw e;
+            }
+            bsBuff <<= 8;
+            bsLive -= 8;
+        }
+        bsBuff |= (v << (32 - bsLive - n));
+        bsLive += n;
+    }
+
+    private void doReversibleTransformation()
+    {
+        int i;
+
+        workLimit = workFactor * last;
+        workDone = 0;
+        blockRandomised = false;
+        firstAttempt = true;
+
+        mainSort();
+
+        if (workDone > workLimit && firstAttempt)
+        {
+            randomiseBlock();
+            workLimit = 0;
+            workDone = 0;
+            blockRandomised = true;
+            firstAttempt = false;
+            mainSort();
+        }
+
+        origPtr = -1;
+        for (i = 0; i <= last; i++)
+        {
+            if (zptr[i] == 0)
+            {
+                origPtr = i;
+                break;
+            }
+        }
+
+        if (origPtr == -1)
+        {
+            panic();
+        }
+    }
+
+    private void endBlock()
+            throws IOException
+    {
+        blockCRC = crc.getFinalCRC();
+        combinedCRC = (combinedCRC << 1) | (combinedCRC >>> 31);
+        combinedCRC ^= blockCRC;
+
+        /*
+         * sort the block and establish posn of original string
+         */
+        doReversibleTransformation();
+
+        /*
+         * A 6-byte block header, the value chosen arbitrarily
+         * as 0x314159265359 :-).  A 32 bit value does not really
+         * give a strong enough guarantee that the value will not
+         * appear by chance in the compressed datastream.  Worst-case
+         * probability of this event, for a 900k block, is about
+         * 2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
+         * For a compressed file of size 100Gb -- about 100000 blocks --
+         * only a 48-bit marker will do.  NB: normal compression/
+         * decompression do *not* rely on these statistical properties.
+         * They are only important when trying to recover blocks from
+         * damaged files.
+         */
+        bsPutUChar(0x31);
+        bsPutUChar(0x41);
+        bsPutUChar(0x59);
+        bsPutUChar(0x26);
+        bsPutUChar(0x53);
+        bsPutUChar(0x59);
+
+        /*
+         * Now the block's CRC, so it is in a known place.
+         */
+        bsPutint(blockCRC);
+
+        /*
+         * Now a single bit indicating randomisation.
+         */
+        if (blockRandomised)
+        {
+            bsW(1, 1);
+        }
+        else
+        {
+            bsW(1, 0);
+        }
+
+        /*
+         * Finally, block's contents proper.
+         */
+        moveToFrontCodeAndSend();
+    }
+
+    private void endCompression()
+            throws IOException
+    {
+        /*
+         * Now another magic 48-bit number, 0x177245385090, to
+         * indicate the end of the last block.  (sqrt(pi), if
+         * you want to know.  I did want to use e, but it contains
+         * too much repetition -- 27 18 28 18 28 46 -- for me
+         * to feel statistically comfortable.  Call me paranoid.)
+         */
+        bsPutUChar(0x17);
+        bsPutUChar(0x72);
+        bsPutUChar(0x45);
+        bsPutUChar(0x38);
+        bsPutUChar(0x50);
+        bsPutUChar(0x90);
+
+        bsPutint(combinedCRC);
+
+        bsFinishedWithStream();
+    }
+
+    private boolean fullGtU(int i1, int i2)
+    {
+        int k;
+        char c1;
+        char c2;
+        int s1;
+        int s2;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        c1 = block[i1 + 1];
+        c2 = block[i2 + 1];
+        if (c1 != c2)
+        {
+            return (c1 > c2);
+        }
+        i1++;
+        i2++;
+
+        k = last + 1;
+
+        do
+        {
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2)
+            {
+                return (c1 > c2);
+            }
+            s1 = quadrant[i1];
+            s2 = quadrant[i2];
+            if (s1 != s2)
+            {
+                return (s1 > s2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2)
+            {
+                return (c1 > c2);
+            }
+            s1 = quadrant[i1];
+            s2 = quadrant[i2];
+            if (s1 != s2)
+            {
+                return (s1 > s2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2)
+            {
+                return (c1 > c2);
+            }
+            s1 = quadrant[i1];
+            s2 = quadrant[i2];
+            if (s1 != s2)
+            {
+                return (s1 > s2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2)
+            {
+                return (c1 > c2);
+            }
+            s1 = quadrant[i1];
+            s2 = quadrant[i2];
+            if (s1 != s2)
+            {
+                return (s1 > s2);
+            }
+            i1++;
+            i2++;
+
+            if (i1 > last)
+            {
+                i1 -= last;
+                i1--;
+            }
+
+            if (i2 > last)
+            {
+                i2 -= last;
+                i2--;
+            }
+
+            k -= 4;
+            workDone++;
+        }
+        while (k >= 0);
+
+        return false;
+    }
+
+    private void generateMTFValues()
+    {
+        char[] yy = new char[256];
+        int i;
+        int j;
+        char tmp;
+        char tmp2;
+        int zPend;
+        int wr;
+        int EOB;
+
+        makeMaps();
+        EOB = nInUse + 1;
+
+        for (i = 0; i <= EOB; i++)
+        {
+            mtfFreq[i] = 0;
+        }
+
+        wr = 0;
+        zPend = 0;
+        for (i = 0; i < nInUse; i++)
+        {
+            yy[i] = (char) i;
+        }
+
+        for (i = 0; i <= last; i++)
+        {
+            char ll_i;
+
+            ll_i = unseqToSeq[block[zptr[i]]];
+
+            j = 0;
+            tmp = yy[j];
+            while (ll_i != tmp)
+            {
+                j++;
+                tmp2 = tmp;
+                tmp = yy[j];
+                yy[j] = tmp2;
+            }
+
+            yy[0] = tmp;
+
+            if (j == 0)
+            {
+                zPend++;
+            }
+            else
+            {
+                if (zPend > 0)
+                {
+                    zPend--;
+                    while (true)
+                    {
+                        switch (zPend % 2)
+                        {
+                            case 0:
+                                szptr[wr] = (short) RUNA;
+                                wr++;
+                                mtfFreq[RUNA]++;
+                                break;
+                            case 1:
+                                szptr[wr] = (short) RUNB;
+                                wr++;
+                                mtfFreq[RUNB]++;
+                                break;
+                        }
+
+                        if (zPend < 2)
+                        {
+                            break;
+                        }
+                        zPend = (zPend - 2) / 2;
+                    }
+
+                    zPend = 0;
+                }
+                szptr[wr] = (short) (j + 1);
+                wr++;
+                mtfFreq[j + 1]++;
+            }
+        }
+
+        if (zPend > 0)
+        {
+            zPend--;
+            while (true)
+            {
+                switch (zPend % 2)
+                {
+                    case 0:
+                        szptr[wr] = (short) RUNA;
+                        wr++;
+                        mtfFreq[RUNA]++;
+                        break;
+                    case 1:
+                        szptr[wr] = (short) RUNB;
+                        wr++;
+                        mtfFreq[RUNB]++;
+                        break;
+                }
+                if (zPend < 2)
+                {
+                    break;
+                }
+                zPend = (zPend - 2) / 2;
+            }
+        }
+
+        szptr[wr] = (short) EOB;
+        wr++;
+        mtfFreq[EOB]++;
+
+        nMTF = wr;
+    }
+
+    private void hbAssignCodes(int[] code, char[] length, int minLen,
+                               int maxLen, int alphaSize)
+    {
+        int n;
+        int vec;
+        int i;
+
+        vec = 0;
+        for (n = minLen; n <= maxLen; n++)
+        {
+            for (i = 0; i < alphaSize; i++)
+            {
+                if (length[i] == n)
+                {
+                    code[i] = vec;
+                    vec++;
+                }
+            }
+
+            vec <<= 1;
+        }
+    }
+
+    private void initBlock()
+    {
+        //        blockNo++;
+        crc.initialiseCRC();
+        last = -1;
+        //        ch = 0;
+
+        for (int i = 0; i < 256; i++)
+        {
+            inUse[i] = false;
+        }
+
+        /*
+         * 20 is just a paranoia constant
+         */
+        allowableBlockSize = BASE_BLOCK_SIZE * blockSize100k - 20;
+    }
+
+    private void initialize()
+            throws IOException
+    {
+        /*
+         * Write `magic' bytes h indicating file-format == huffmanised,
+         * followed by a digit indicating blockSize100k.
+         */
+        bsPutUChar('h');
+        bsPutUChar('0' + blockSize100k);
+
+        combinedCRC = 0;
+    }
+
+    private void mainSort()
+    {
+        int i;
+        int j;
+        int ss;
+        int sb;
+        int[] runningOrder = new int[256];
+        int[] copy = new int[256];
+        boolean[] bigDone = new boolean[256];
+        int c1;
+        int c2;
+
+        /*
+         * In the various block-sized structures, live data runs
+         * from 0 to last+NUM_OVERSHOOT_BYTES inclusive.  First,
+         * set up the overshoot area for block.
+         */
+        //   if (verbosity >= 4) fprintf ( stderr, "        sort initialise ...\n" );
+        for (i = 0; i < NUM_OVERSHOOT_BYTES; i++)
+        {
+            block[last + i + 2] = block[(i % (last + 1)) + 1];
+        }
+        for (i = 0; i <= last + NUM_OVERSHOOT_BYTES; i++)
+        {
+            quadrant[i] = 0;
+        }
+
+        block[0] = block[last + 1];
+
+        if (last < 4000)
+        {
+            /*
+             * Use simpleSort(), since the full sorting mechanism
+             * has quite a large constant overhead.
+             */
+            for (i = 0; i <= last; i++)
+            {
+                zptr[i] = i;
+            }
+            firstAttempt = false;
+            workDone = 0;
+            workLimit = 0;
+            simpleSort(0, last, 0);
+        }
+        else
+        {
+            for (i = 0; i <= 255; i++)
+            {
+                bigDone[i] = false;
+            }
+
+            for (i = 0; i <= 65536; i++)
+            {
+                ftab[i] = 0;
+            }
+
+            c1 = block[0];
+            for (i = 0; i <= last; i++)
+            {
+                c2 = block[i + 1];
+                ftab[(c1 << 8) + c2]++;
+                c1 = c2;
+            }
+
+            for (i = 1; i <= 65536; i++)
+            {
+                ftab[i] += ftab[i - 1];
+            }
+
+            c1 = block[1];
+            for (i = 0; i < last; i++)
+            {
+                c2 = block[i + 2];
+                j = (c1 << 8) + c2;
+                c1 = c2;
+                ftab[j]--;
+                zptr[ftab[j]] = i;
+            }
+
+            j = ((block[last + 1]) << 8) + (block[1]);
+            ftab[j]--;
+            zptr[ftab[j]] = last;
+
+            /*
+             * Now ftab contains the first loc of every small bucket.
+             * Calculate the running order, from smallest to largest
+             * big bucket.
+             */
+            for (i = 0; i <= 255; i++)
+            {
+                runningOrder[i] = i;
+            }
+            {
+                int vv;
+                int h = 1;
+                do
+                {
+                    h = 3 * h + 1;
+                }
+                while (h <= 256);
+                do
+                {
+                    h = h / 3;
+                    for (i = h; i <= 255; i++)
+                    {
+                        vv = runningOrder[i];
+                        j = i;
+                        while ((ftab[((runningOrder[j - h]) + 1) << 8]
+                                - ftab[(runningOrder[j - h]) << 8]) >
+                                (ftab[((vv) + 1) << 8] - ftab[(vv) << 8]))
+                        {
+                            runningOrder[j] = runningOrder[j - h];
+                            j = j - h;
+                            if (j <= (h - 1))
+                            {
+                                break;
+                            }
+                        }
+                        runningOrder[j] = vv;
+                    }
+                }
+                while (h != 1);
+            }
+
+            /*
+             * The main sorting loop.
+             */
+            for (i = 0; i <= 255; i++)
+            {
+
+                /*
+                 * Process big buckets, starting with the least full.
+                 */
+                ss = runningOrder[i];
+
+                /*
+                 * Complete the big bucket [ss] by quicksorting
+                 * any unsorted small buckets [ss, j].  Hopefully
+                 * previous pointer-scanning phases have already
+                 * completed many of the small buckets [ss, j], so
+                 * we don't have to sort them at all.
+                 */
+                for (j = 0; j <= 255; j++)
+                {
+                    sb = (ss << 8) + j;
+                    if (!((ftab[sb] & SETMASK) == SETMASK))
+                    {
+                        int lo = ftab[sb] & CLEARMASK;
+                        int hi = (ftab[sb + 1] & CLEARMASK) - 1;
+                        if (hi > lo)
+                        {
+                            qSort3(lo, hi, 2);
+                            if (workDone > workLimit && firstAttempt)
+                            {
+                                return;
+                            }
+                        }
+                        ftab[sb] |= SETMASK;
+                    }
+                }
+
+                /*
+                 * The ss big bucket is now done.  Record this fact,
+                 * and update the quadrant descriptors.  Remember to
+                 * update quadrants in the overshoot area too, if
+                 * necessary.  The "if (i < 255)" test merely skips
+                 * this updating for the last bucket processed, since
+                 * updating for the last bucket is pointless.
+                 */
+                bigDone[ss] = true;
+
+                if (i < 255)
+                {
+                    int bbStart = ftab[ss << 8] & CLEARMASK;
+                    int bbSize = (ftab[(ss + 1) << 8] & CLEARMASK) - bbStart;
+                    int shifts = 0;
+
+                    while ((bbSize >> shifts) > 65534)
+                    {
+                        shifts++;
+                    }
+
+                    for (j = 0; j < bbSize; j++)
+                    {
+                        int a2update = zptr[bbStart + j];
+                        int qVal = (j >> shifts);
+                        quadrant[a2update] = qVal;
+                        if (a2update < NUM_OVERSHOOT_BYTES)
+                        {
+                            quadrant[a2update + last + 1] = qVal;
+                        }
+                    }
+
+                    if (!(((bbSize - 1) >> shifts) <= 65535))
+                    {
+                        panic();
+                    }
+                }
+
+                /*
+                 * Now scan this big bucket so as to synthesise the
+                 * sorted order for small buckets [t, ss] for all t != ss.
+                 */
+                for (j = 0; j <= 255; j++)
+                {
+                    copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
+                }
+
+                for (j = ftab[ss << 8] & CLEARMASK;
+                     j < (ftab[(ss + 1) << 8] & CLEARMASK); j++)
+                {
+                    c1 = block[zptr[j]];
+                    if (!bigDone[c1])
+                    {
+                        zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
+                        copy[c1]++;
+                    }
+                }
+
+                for (j = 0; j <= 255; j++)
+                {
+                    ftab[(j << 8) + ss] |= SETMASK;
+                }
+            }
+        }
+    }
+
+    private void makeMaps()
+    {
+        int i;
+        nInUse = 0;
+        for (i = 0; i < 256; i++)
+        {
+            if (inUse[i])
+            {
+                seqToUnseq[nInUse] = (char) i;
+                unseqToSeq[i] = (char) nInUse;
+                nInUse++;
+            }
+        }
+    }
+
+    private char med3(char a, char b, char c)
+    {
+        char t;
+        if (a > b)
+        {
+            t = a;
+            a = b;
+            b = t;
+        }
+        if (b > c)
+        {
+            t = b;
+            b = c;
+            c = t;
+        }
+        if (a > b)
+        {
+            b = a;
+        }
+        return b;
+    }
+
+    private void moveToFrontCodeAndSend()
+            throws IOException
+    {
+        bsPutIntVS(24, origPtr);
+        generateMTFValues();
+        sendMTFValues();
+    }
+
+    private void qSort3(int loSt, int hiSt, int dSt)
+    {
+        int unLo;
+        int unHi;
+        int ltLo;
+        int gtHi;
+        int med;
+        int n;
+        int m;
+        int sp;
+        int lo;
+        int hi;
+        int d;
+        StackElem[] stack = new StackElem[QSORT_STACK_SIZE];
+        for (int count = 0; count < QSORT_STACK_SIZE; count++)
+        {
+            stack[count] = new StackElem();
+        }
+
+        sp = 0;
+
+        stack[sp].m_ll = loSt;
+        stack[sp].m_hh = hiSt;
+        stack[sp].m_dd = dSt;
+        sp++;
+
+        while (sp > 0)
+        {
+            if (sp >= QSORT_STACK_SIZE)
+            {
+                panic();
+            }
+
+            sp--;
+            lo = stack[sp].m_ll;
+            hi = stack[sp].m_hh;
+            d = stack[sp].m_dd;
+
+            if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH)
+            {
+                simpleSort(lo, hi, d);
+                if (workDone > workLimit && firstAttempt)
+                {
+                    return;
+                }
+                continue;
+            }
+
+            med = med3(block[zptr[lo] + d + 1],
+                    block[zptr[hi] + d + 1],
+                    block[zptr[(lo + hi) >> 1] + d + 1]);
+
+            unLo = lo;
+            ltLo = lo;
+            unHi = hi;
+            gtHi = hi;
+
+            while (true)
+            {
+                while (true)
+                {
+                    if (unLo > unHi)
+                    {
+                        break;
+                    }
+                    n = block[zptr[unLo] + d + 1] - med;
+                    if (n == 0)
+                    {
+                        int temp = 0;
+                        temp = zptr[unLo];
+                        zptr[unLo] = zptr[ltLo];
+                        zptr[ltLo] = temp;
+                        ltLo++;
+                        unLo++;
+                        continue;
+                    }
+
+                    if (n > 0)
+                    {
+                        break;
+                    }
+                    unLo++;
+                }
+                while (true)
+                {
+                    if (unLo > unHi)
+                    {
+                        break;
+                    }
+                    n = block[zptr[unHi] + d + 1] - med;
+                    if (n == 0)
+                    {
+                        int temp = 0;
+                        temp = zptr[unHi];
+                        zptr[unHi] = zptr[gtHi];
+                        zptr[gtHi] = temp;
+                        gtHi--;
+                        unHi--;
+                        continue;
+                    }
+
+                    if (n < 0)
+                    {
+                        break;
+                    }
+                    unHi--;
+                }
+                if (unLo > unHi)
+                {
+                    break;
+                }
+                int temp = 0;
+                temp = zptr[unLo];
+                zptr[unLo] = zptr[unHi];
+                zptr[unHi] = temp;
+                unLo++;
+                unHi--;
+            }
+
+            if (gtHi < ltLo)
+            {
+                stack[sp].m_ll = lo;
+                stack[sp].m_hh = hi;
+                stack[sp].m_dd = d + 1;
+                sp++;
+                continue;
+            }
+
+            n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo) : (unLo - ltLo);
+            vswap(lo, unLo - n, n);
+            m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi) : (gtHi - unHi);
+            vswap(unLo, hi - m + 1, m);
+
+            n = lo + unLo - ltLo - 1;
+            m = hi - (gtHi - unHi) + 1;
+
+            stack[sp].m_ll = lo;
+            stack[sp].m_hh = n;
+            stack[sp].m_dd = d;
+            sp++;
+
+            stack[sp].m_ll = n + 1;
+            stack[sp].m_hh = m - 1;
+            stack[sp].m_dd = d + 1;
+            sp++;
+
+            stack[sp].m_ll = m;
+            stack[sp].m_hh = hi;
+            stack[sp].m_dd = d;
+            sp++;
+        }
+    }
+
+    private void randomiseBlock()
+    {
+        int i;
+        int rNToGo = 0;
+        int rTPos = 0;
+        for (i = 0; i < 256; i++)
+        {
+            inUse[i] = false;
+        }
+
+        for (i = 0; i <= last; i++)
+        {
+            if (rNToGo == 0)
+            {
+                rNToGo = (char) RAND_NUMS[rTPos];
+                rTPos++;
+                if (rTPos == 512)
+                {
+                    rTPos = 0;
+                }
+            }
+            rNToGo--;
+            block[i + 1] ^= ((rNToGo == 1) ? 1 : 0);
+            // handle 16 bit signed numbers
+            block[i + 1] &= 0xFF;
+
+            inUse[block[i + 1]] = true;
+        }
+    }
+
+    private void sendMTFValues()
+            throws IOException
+    {
+        char[][] len = new char[N_GROUPS][MAX_ALPHA_SIZE];
+
+        int v;
+
+        int t;
+
+        int i;
+
+        int j;
+
+        int gs;
+
+        int ge;
+
+        int bt;
+
+        int bc;
+
+        int iter;
+        int nSelectors = 0;
+        int alphaSize;
+        int minLen;
+        int maxLen;
+        int selCtr;
+        int nGroups;
+
+        alphaSize = nInUse + 2;
+        for (t = 0; t < N_GROUPS; t++)
+        {
+            for (v = 0; v < alphaSize; v++)
+            {
+                len[t][v] = (char) GREATER_ICOST;
+            }
+        }
+
+        /*
+         * Decide how many coding tables to use
+         */
+        if (nMTF <= 0)
+        {
+            panic();
+        }
+
+        if (nMTF < 200)
+        {
+            nGroups = 2;
+        }
+        else if (nMTF < 600)
+        {
+            nGroups = 3;
+        }
+        else if (nMTF < 1200)
+        {
+            nGroups = 4;
+        }
+        else if (nMTF < 2400)
+        {
+            nGroups = 5;
+        }
+        else
+        {
+            nGroups = 6;
+        }
+        {
+            /*
+             * Generate an initial set of coding tables
+             */
+            int nPart;
+            int remF;
+            int tFreq;
+            int aFreq;
+
+            nPart = nGroups;
+            remF = nMTF;
+            gs = 0;
+            while (nPart > 0)
+            {
+                tFreq = remF / nPart;
+                ge = gs - 1;
+                aFreq = 0;
+                while (aFreq < tFreq && ge < alphaSize - 1)
+                {
+                    ge++;
+                    aFreq += mtfFreq[ge];
+                }
+
+                if (ge > gs && nPart != nGroups && nPart != 1
+                        && ((nGroups - nPart) % 2 == 1))
+                {
+                    aFreq -= mtfFreq[ge];
+                    ge--;
+                }
+
+                for (v = 0; v < alphaSize; v++)
+                {
+                    if (v >= gs && v <= ge)
+                    {
+                        len[nPart - 1][v] = (char) LESSER_ICOST;
+                    }
+                    else
+                    {
+                        len[nPart - 1][v] = (char) GREATER_ICOST;
+                    }
+                }
+
+                nPart--;
+                gs = ge + 1;
+                remF -= aFreq;
+            }
+        }
+
+        int[][] rfreq = new int[N_GROUPS][MAX_ALPHA_SIZE];
+        int[] fave = new int[N_GROUPS];
+        short[] cost = new short[N_GROUPS];
+        /*
+         * Iterate up to N_ITERS times to improve the tables.
+         */
+        for (iter = 0; iter < N_ITERS; iter++)
+        {
+            for (t = 0; t < nGroups; t++)
+            {
+                fave[t] = 0;
+            }
+
+            for (t = 0; t < nGroups; t++)
+            {
+                for (v = 0; v < alphaSize; v++)
+                {
+                    rfreq[t][v] = 0;
+                }
+            }
+
+            nSelectors = 0;
+            gs = 0;
+            while (true)
+            {
+
+                /*
+                 * Set group start & end marks.
+                 */
+                if (gs >= nMTF)
+                {
+                    break;
+                }
+                ge = gs + G_SIZE - 1;
+                if (ge >= nMTF)
+                {
+                    ge = nMTF - 1;
+                }
+
+                /*
+                 * Calculate the cost of this group as coded
+                 * by each of the coding tables.
+                 */
+                for (t = 0; t < nGroups; t++)
+                {
+                    cost[t] = 0;
+                }
+
+                if (nGroups == 6)
+                {
+                    short cost0 = 0;
+                    short cost1 = 0;
+                    short cost2 = 0;
+                    short cost3 = 0;
+                    short cost4 = 0;
+                    short cost5 = 0;
+
+                    for (i = gs; i <= ge; i++)
+                    {
+                        short icv = szptr[i];
+                        cost0 += len[0][icv];
+                        cost1 += len[1][icv];
+                        cost2 += len[2][icv];
+                        cost3 += len[3][icv];
+                        cost4 += len[4][icv];
+                        cost5 += len[5][icv];
+                    }
+                    cost[0] = cost0;
+                    cost[1] = cost1;
+                    cost[2] = cost2;
+                    cost[3] = cost3;
+                    cost[4] = cost4;
+                    cost[5] = cost5;
+                }
+                else
+                {
+                    for (i = gs; i <= ge; i++)
+                    {
+                        short icv = szptr[i];
+                        for (t = 0; t < nGroups; t++)
+                        {
+                            cost[t] += len[t][icv];
+                        }
+                    }
+                }
+
+                /*
+                 * Find the coding table which is best for this group,
+                 * and record its identity in the selector table.
+                 */
+                bc = 999999999;
+                bt = -1;
+                for (t = 0; t < nGroups; t++)
+                {
+                    if (cost[t] < bc)
+                    {
+                        bc = cost[t];
+                        bt = t;
+                    }
+                }
+
+                fave[bt]++;
+                selector[nSelectors] = (char) bt;
+                nSelectors++;
+
+                /*
+                 * Increment the symbol frequencies for the selected table.
+                 */
+                for (i = gs; i <= ge; i++)
+                {
+                    rfreq[bt][szptr[i]]++;
+                }
+
+                gs = ge + 1;
+            }
+
+            /*
+             * Recompute the tables based on the accumulated frequencies.
+             */
+            for (t = 0; t < nGroups; t++)
+            {
+                hbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
+            }
+        }
+
+        rfreq = null;
+        fave = null;
+        cost = null;
+
+        if (!(nGroups < 8))
+        {
+            panic();
+        }
+        if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / G_SIZE))))
+        {
+            panic();
+        }
+        {
+            /*
+             * Compute MTF values for the selectors.
+             */
+            char[] pos = new char[N_GROUPS];
+            char ll_i;
+            char tmp2;
+            char tmp;
+            for (i = 0; i < nGroups; i++)
+            {
+                pos[i] = (char) i;
+            }
+            for (i = 0; i < nSelectors; i++)
+            {
+                ll_i = selector[i];
+                j = 0;
+                tmp = pos[j];
+                while (ll_i != tmp)
+                {
+                    j++;
+                    tmp2 = tmp;
+                    tmp = pos[j];
+                    pos[j] = tmp2;
+                }
+                pos[0] = tmp;
+                selectorMtf[i] = (char) j;
+            }
+        }
+
+        int[][] code = new int[N_GROUPS][MAX_ALPHA_SIZE];
+
+        /*
+         * Assign actual codes for the tables.
+         */
+        for (t = 0; t < nGroups; t++)
+        {
+            minLen = 32;
+            maxLen = 0;
+            for (i = 0; i < alphaSize; i++)
+            {
+                if (len[t][i] > maxLen)
+                {
+                    maxLen = len[t][i];
+                }
+                if (len[t][i] < minLen)
+                {
+                    minLen = len[t][i];
+                }
+            }
+            if (maxLen > 20)
+            {
+                panic();
+            }
+            if (minLen < 1)
+            {
+                panic();
+            }
+            hbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
+        }
+        {
+            /*
+             * Transmit the mapping table.
+             */
+            boolean[] inUse16 = new boolean[16];
+            for (i = 0; i < 16; i++)
+            {
+                inUse16[i] = false;
+                for (j = 0; j < 16; j++)
+                {
+                    if (inUse[i * 16 + j])
+                    {
+                        inUse16[i] = true;
+                    }
+                }
+            }
+
+            for (i = 0; i < 16; i++)
+            {
+                if (inUse16[i])
+                {
+                    bsW(1, 1);
+                }
+                else
+                {
+                    bsW(1, 0);
+                }
+            }
+
+            for (i = 0; i < 16; i++)
+            {
+                if (inUse16[i])
+                {
+                    for (j = 0; j < 16; j++)
+                    {
+                        if (inUse[i * 16 + j])
+                        {
+                            bsW(1, 1);
+                        }
+                        else
+                        {
+                            bsW(1, 0);
+                        }
+                    }
+                }
+            }
+
+        }
+
+        /*
+         * Now the selectors.
+         */
+        bsW(3, nGroups);
+        bsW(15, nSelectors);
+        for (i = 0; i < nSelectors; i++)
+        {
+            for (j = 0; j < selectorMtf[i]; j++)
+            {
+                bsW(1, 1);
+            }
+            bsW(1, 0);
+        }
+
+        for (t = 0; t < nGroups; t++)
+        {
+            int curr = len[t][0];
+            bsW(5, curr);
+            for (i = 0; i < alphaSize; i++)
+            {
+                while (curr < len[t][i])
+                {
+                    bsW(2, 2);
+                    curr++;
+                    /*
+                     * 10
+                     */
+                }
+                while (curr > len[t][i])
+                {
+                    bsW(2, 3);
+                    curr--;
+                    /*
+                     * 11
+                     */
+                }
+                bsW(1, 0);
+            }
+        }
+
+        /*
+         * And finally, the block data proper
+         */
+        selCtr = 0;
+        gs = 0;
+        while (true)
+        {
+            if (gs >= nMTF)
+            {
+                break;
+            }
+            ge = gs + G_SIZE - 1;
+            if (ge >= nMTF)
+            {
+                ge = nMTF - 1;
+            }
+            for (i = gs; i <= ge; i++)
+            {
+                bsW(len[selector[selCtr]][szptr[i]],
+                        code[selector[selCtr]][szptr[i]]);
+            }
+
+            gs = ge + 1;
+            selCtr++;
+        }
+        if (!(selCtr == nSelectors))
+        {
+            panic();
+        }
+    }
+
+    private void simpleSort(int lo, int hi, int d)
+    {
+        int i;
+        int j;
+        int h;
+        int bigN;
+        int hp;
+        int v;
+
+        bigN = hi - lo + 1;
+        if (bigN < 2)
+        {
+            return;
+        }
+
+        hp = 0;
+        while (incs[hp] < bigN)
+        {
+            hp++;
+        }
+        hp--;
+
+        for (; hp >= 0; hp--)
+        {
+            h = incs[hp];
+
+            i = lo + h;
+            while (true)
+            {
+                /*
+                 * copy 1
+                 */
+                if (i > hi)
+                {
+                    break;
+                }
+                v = zptr[i];
+                j = i;
+                while (fullGtU(zptr[j - h] + d, v + d))
+                {
+                    zptr[j] = zptr[j - h];
+                    j = j - h;
+                    if (j <= (lo + h - 1))
+                    {
+                        break;
+                    }
+                }
+                zptr[j] = v;
+                i++;
+
+                /*
+                 * copy 2
+                 */
+                if (i > hi)
+                {
+                    break;
+                }
+                v = zptr[i];
+                j = i;
+                while (fullGtU(zptr[j - h] + d, v + d))
+                {
+                    zptr[j] = zptr[j - h];
+                    j = j - h;
+                    if (j <= (lo + h - 1))
+                    {
+                        break;
+                    }
+                }
+                zptr[j] = v;
+                i++;
+
+                /*
+                 * copy 3
+                 */
+                if (i > hi)
+                {
+                    break;
+                }
+                v = zptr[i];
+                j = i;
+                while (fullGtU(zptr[j - h] + d, v + d))
+                {
+                    zptr[j] = zptr[j - h];
+                    j = j - h;
+                    if (j <= (lo + h - 1))
+                    {
+                        break;
+                    }
+                }
+                zptr[j] = v;
+                i++;
+
+                if (workDone > workLimit && firstAttempt)
+                {
+                    return;
+                }
+            }
+        }
+    }
+
+    private void vswap(int p1, int p2, int n)
+    {
+        int temp = 0;
+        while (n > 0)
+        {
+            temp = zptr[p1];
+            zptr[p1] = zptr[p2];
+            zptr[p2] = temp;
+            p1++;
+            p2++;
+            n--;
+        }
+    }
+
+    private void writeRun()
+            throws IOException
+    {
+        if (last < allowableBlockSize)
+        {
+            inUse[currentChar] = true;
+            for (int i = 0; i < runLength; i++)
+            {
+                crc.updateCRC((char) currentChar);
+            }
+            switch (runLength)
+            {
+                case 1:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                case 2:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                case 3:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                default:
+                    inUse[runLength - 4] = true;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) (runLength - 4);
+                    break;
+            }
+        }
+        else
+        {
+            endBlock();
+            initBlock();
+            writeRun();
+        }
+    }
+
+    private static class StackElem
+    {
+        int m_dd;
+        int m_hh;
+        int m_ll;
+    }
+}
+
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CRC.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CRC.java
new file mode 100644
index 0000000..207ed29
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/CRC.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.bzip2;
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron@aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+/**
+ * A simple class the hold and calculate the CRC for sanity checking of the
+ * data.
+ *
+ * @author <a href="mailto:keiron@aftexsw.com">Keiron Liddle</a>
+ */
+class CRC
+{
+    private static int[] CRC32_TABLE = new int[]
+    {
+        0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+        0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+        0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+        0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+        0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+        0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+        0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+        0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+        0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+        0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+        0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+        0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+        0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+        0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+        0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+        0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+        0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+        0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+        0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+        0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+        0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+        0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+        0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+        0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+        0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+        0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+        0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+        0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+        0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+        0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+        0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+        0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+        0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+        0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+        0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+        0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+        0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+        0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+        0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+        0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+        0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+        0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+        0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+        0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+        0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+        0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+        0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+        0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+        0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+        0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+        0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+        0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+        0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+        0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+        0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+        0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+        0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+        0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+        0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+        0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+        0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+        0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+        0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+        0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+    };
+
+    private int m_globalCrc;
+
+    protected CRC()
+    {
+        initialiseCRC();
+    }
+
+    int getFinalCRC()
+    {
+        return ~m_globalCrc;
+    }
+
+    void initialiseCRC()
+    {
+        m_globalCrc = 0xffffffff;
+    }
+
+    void updateCRC(final int inCh)
+    {
+        int temp = (m_globalCrc >> 24) ^ inCh;
+        if (temp < 0)
+        {
+            temp = 256 + temp;
+        }
+        m_globalCrc = (m_globalCrc << 8) ^ CRC32_TABLE[temp];
+    }
+}
+
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/package.html
new file mode 100644
index 0000000..ebb546e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/bzip2/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The BZIP2 File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileObject.java
new file mode 100644
index 0000000..4b5991f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileObject.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.compressed;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+
+/**
+ * A compressed file.<br>
+ * Such a file do only have one child (the compressed filename with stripped last extension)
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class CompressedFileFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    private final FileObject container;
+    private final String[] children;
+
+    protected CompressedFileFileObject(FileName name, FileObject container, CompressedFileFileSystem fs)
+    {
+        super(name, fs);
+        this.container = container;
+
+        // todo, add getBaseName(String) to FileName
+        String basename = container.getName().getBaseName();
+        int pos = basename.lastIndexOf('.');
+        basename = basename.substring(0, pos);
+
+        children = new String[]
+        {
+            basename
+        };
+    }
+
+    /**
+     * Determines if this file can be written to.
+     *
+     * @return <code>true</code> if this file is writeable, <code>false</code> if not.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isWriteable() throws FileSystemException
+    {
+        return getFileSystem().hasCapability(Capability.WRITE_CONTENT);
+    }
+
+    /**
+     * Returns the file's type.
+     */
+    protected FileType doGetType() throws FileSystemException
+    {
+        if (getName().getPath().endsWith("/"))
+        {
+            return FileType.FOLDER;
+        }
+        else
+        {
+            return FileType.FILE;
+        }
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren()
+    {
+        return children;
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).  Is only called if
+     * {@link #doGetType} returns {@link FileType#FILE}.
+     */
+    protected long doGetContentSize()
+    {
+        return -1;
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        return container.getContent().getLastModifiedTime();
+    }
+
+    protected FileObject getContainer()
+    {
+        return container;
+    }
+
+    public void createFile() throws FileSystemException
+    {
+        container.createFile();
+        injectType(FileType.FILE);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileProvider.java
new file mode 100644
index 0000000..4a92806
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileProvider.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.compressed;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractLayeredFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.LayeredFileName;
+
+import java.util.Collection;
+
+/**
+ * A file system provider for compressed files.  Provides read-only file
+ * systems.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class CompressedFileFileProvider
+    extends AbstractLayeredFileProvider
+    implements FileProvider
+{
+    public CompressedFileFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Parses an absolute URI.
+     *
+     * @param uri The URI to parse.
+     */
+    /*
+    public FileName parseUri(final String uri)
+        throws FileSystemException
+    {
+        return ZipFileName.parseUri(uri);
+    }
+    */
+
+    /**
+     * Creates a layered file system.  This method is called if the file system
+     * is not cached.
+     *
+     * @param scheme The URI scheme.
+     * @param file   The file to create the file system on top of.
+     * @return The file system.
+     */
+    protected FileSystem doCreateFileSystem(final String scheme,
+                                            final FileObject file,
+                                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        final FileName name =
+            new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
+        return createFileSystem(name, file, fileSystemOptions);
+    }
+
+    protected abstract FileSystem createFileSystem(final FileName name, final FileObject file,
+                                                   final FileSystemOptions fileSystemOptions)
+        throws FileSystemException;
+
+    public abstract Collection getCapabilities();
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileSystem.java
new file mode 100644
index 0000000..d2a1ca1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/CompressedFileFileSystem.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.compressed;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.util.Collection;
+
+/**
+ * A read-only file system for compressed files.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class CompressedFileFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    protected CompressedFileFileSystem(final FileName rootName,
+                                       final FileObject parentLayer,
+                                       final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+    }
+
+    public void init() throws FileSystemException
+    {
+        super.init();
+
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected abstract void addCapabilities(final Collection caps);
+
+    /**
+     * Creates a file object.
+     */
+    protected abstract FileObject createFile(final FileName name) throws FileSystemException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/package.html
new file mode 100644
index 0000000..433ecef
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/compressed/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The compressed file provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FTPClientWrapper.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FTPClientWrapper.java
new file mode 100644
index 0000000..a2efdec
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FTPClientWrapper.java
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPReply;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.provider.GenericFileName;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * A wrapper to the FTPClient to allow automatic reconnect on connection loss.<br />
+ * I decided to not to use eg. noop() to determine the state of the connection to avoid
+ * unnecesary server round-trips.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class FTPClientWrapper implements FtpClient
+{
+    private final GenericFileName root;
+    private final FileSystemOptions fileSystemOptions;
+
+    private FTPClient ftpClient;
+
+    FTPClientWrapper(final GenericFileName root, final FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        this.root = root;
+        this.fileSystemOptions = fileSystemOptions;
+        getFtpClient(); // fail-fast
+    }
+
+    public GenericFileName getRoot()
+    {
+        return root;
+    }
+
+    public FileSystemOptions getFileSystemOptions()
+    {
+        return fileSystemOptions;
+    }
+
+    private FTPClient createClient() throws FileSystemException
+    {
+        final GenericFileName rootName = getRoot();
+
+        UserAuthenticationData authData = null;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, FtpFileProvider.AUTHENTICATOR_TYPES);
+
+            return FtpClientFactory.createConnection(rootName.getHostName(),
+                rootName.getPort(),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME,
+                        UserAuthenticatorUtils.toChar(rootName.getUserName())),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD,
+                        UserAuthenticatorUtils.toChar(rootName.getPassword())),
+                rootName.getPath(),
+                getFileSystemOptions());
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+    }
+
+    private FTPClient getFtpClient() throws FileSystemException
+    {
+        if (ftpClient == null)
+        {
+            ftpClient = createClient();
+        }
+
+        return ftpClient;
+    }
+
+    public boolean isConnected() throws FileSystemException
+    {
+        return ftpClient != null && ftpClient.isConnected();
+    }
+
+    public void disconnect() throws IOException
+    {
+        try
+        {
+            getFtpClient().disconnect();
+        }
+        finally
+        {
+            ftpClient = null;
+        }
+    }
+
+    public FTPFile[] listFiles(String relPath) throws IOException
+    {
+        try
+        {
+            // VFS-210: return getFtpClient().listFiles(relPath);
+            FTPFile[] files = listFilesInDirectory(relPath);
+            return files;
+        }
+        catch (IOException e)
+        {
+            disconnect();
+
+            FTPFile[] files = listFilesInDirectory(relPath);
+            return files;
+        }
+    }
+
+    private FTPFile[] listFilesInDirectory(String relPath) throws IOException
+    {
+        FTPFile[] files;
+
+        // VFS-307: no check if we can simply list the files, this might fail if there are spaces in the path
+        files = getFtpClient().listFiles(relPath);
+        if (FTPReply.isPositiveCompletion(getFtpClient().getReplyCode()))
+        {
+            return files;
+        }
+
+        // VFS-307: now try the hard way by cd'ing into the directory, list and cd back
+        // if VFS is required to fallback here the user might experience a real bad FTP performance
+        // as then every list requires 4 ftp commands.
+        String workingDirectory = null;
+        if (relPath != null)
+        {
+            workingDirectory = getFtpClient().printWorkingDirectory();
+            if (!getFtpClient().changeWorkingDirectory(relPath))
+            {
+                return null;
+            }
+        }
+
+        files = getFtpClient().listFiles();
+
+        if (relPath != null && !getFtpClient().changeWorkingDirectory(workingDirectory))
+        {
+            throw new FileSystemException("vfs.provider.ftp.wrapper/change-work-directory-back.error",
+                    workingDirectory);
+        }
+        return files;
+    }
+
+    public boolean removeDirectory(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().removeDirectory(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().removeDirectory(relPath);
+        }
+    }
+
+    public boolean deleteFile(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().deleteFile(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().deleteFile(relPath);
+        }
+    }
+
+    public boolean rename(String oldName, String newName) throws IOException
+    {
+        try
+        {
+            return getFtpClient().rename(oldName, newName);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().rename(oldName, newName);
+        }
+    }
+
+    public boolean makeDirectory(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().makeDirectory(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().makeDirectory(relPath);
+        }
+    }
+
+    public boolean completePendingCommand() throws IOException
+    {
+        if (ftpClient != null)
+        {
+            return getFtpClient().completePendingCommand();
+        }
+
+        return true;
+    }
+
+    public InputStream retrieveFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().retrieveFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().retrieveFileStream(relPath);
+        }
+    }
+
+    public InputStream retrieveFileStream(String relPath, long restartOffset) throws IOException
+    {
+        try
+        {
+            FTPClient client = getFtpClient();
+            client.setRestartOffset(restartOffset);
+            return client.retrieveFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+
+            FTPClient client = getFtpClient();
+            client.setRestartOffset(restartOffset);
+            return client.retrieveFileStream(relPath);
+        }
+    }
+
+    public OutputStream appendFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().appendFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().appendFileStream(relPath);
+        }
+    }
+
+    public OutputStream storeFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpClient().storeFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpClient().storeFileStream(relPath);
+        }
+    }
+
+    public boolean abort() throws IOException
+    {
+        try
+        {
+            // imario@apache.org: 2005-02-14
+            // it should be better to really "abort" the transfer, but
+            // currently I didnt manage to make it work - so lets "abort" the hard way.
+            // return getFtpClient().abort();
+
+            disconnect();
+            return true;
+        }
+        catch (IOException e)
+        {
+            disconnect();
+        }
+        return true;
+    }
+
+    public String getReplyString() throws IOException
+    {
+        return getFtpClient().getReplyString();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClient.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClient.java
new file mode 100644
index 0000000..0d7cf16
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClient.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * What VFS expects from an ftp client to provide.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public interface FtpClient
+{
+    boolean isConnected() throws FileSystemException;
+
+    void disconnect() throws IOException;
+
+    FTPFile[] listFiles(String relPath) throws IOException;
+
+    boolean removeDirectory(String relPath) throws IOException;
+
+    boolean deleteFile(String relPath) throws IOException;
+
+    boolean rename(String oldName, String newName) throws IOException;
+
+    boolean makeDirectory(String relPath) throws IOException;
+
+    boolean completePendingCommand() throws IOException;
+
+    InputStream retrieveFileStream(String relPath) throws IOException;
+
+    InputStream retrieveFileStream(String relPath, long restartOffset) throws IOException;
+
+    OutputStream appendFileStream(String relPath) throws IOException;
+
+    OutputStream storeFileStream(String relPath) throws IOException;
+
+    boolean abort() throws IOException;
+
+    String getReplyString() throws IOException;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClientFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClientFactory.java
new file mode 100644
index 0000000..742f355
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpClientFactory.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPReply;
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+import java.io.IOException;
+
+/**
+ * Create a FtpClient instance.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class FtpClientFactory
+{
+    private static final int BUFSZ = 40;
+    private FtpClientFactory()
+    {
+    }
+
+    /**
+     * Creates a new connection to the server.
+     * @param hostname The host name of the server.
+     * @param port The port to connect to.
+     * @param username The name of the user for authentication.
+     * @param password The user's password.
+     * @param workingDirectory The base directory.
+     * @param fileSystemOptions The FileSystemOptions.
+     * @return An FTPClient.
+     * @throws FileSystemException if an error occurs while connecting.
+     */
+    public static FTPClient createConnection(String hostname, int port, char[] username, char[] password,
+                                             String workingDirectory, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        // Determine the username and password to use
+        if (username == null)
+        {
+            username = "anonymous".toCharArray();
+        }
+
+        if (password == null)
+        {
+            password = "anonymous".toCharArray();
+        }
+
+        try
+        {
+            final FTPClient client = new FTPClient();
+
+            String key = FtpFileSystemConfigBuilder.getInstance().getEntryParser(fileSystemOptions);
+            if (key != null)
+            {
+                FTPClientConfig config = new FTPClientConfig(key);
+
+                String serverLanguageCode =
+                        FtpFileSystemConfigBuilder.getInstance().getServerLanguageCode(fileSystemOptions);
+                if (serverLanguageCode != null)
+                {
+                    config.setServerLanguageCode(serverLanguageCode);
+                }
+                String defaultDateFormat =
+                        FtpFileSystemConfigBuilder.getInstance().getDefaultDateFormat(fileSystemOptions);
+                if (defaultDateFormat != null)
+                {
+                    config.setDefaultDateFormatStr(defaultDateFormat);
+                }
+                String recentDateFormat =
+                        FtpFileSystemConfigBuilder.getInstance().getRecentDateFormat(fileSystemOptions);
+                if (recentDateFormat != null)
+                {
+                    config.setRecentDateFormatStr(recentDateFormat);
+                }
+                String serverTimeZoneId =
+                        FtpFileSystemConfigBuilder.getInstance().getServerTimeZoneId(fileSystemOptions);
+                if (serverTimeZoneId != null)
+                {
+                    config.setServerTimeZoneId(serverTimeZoneId);
+                }
+                String[] shortMonthNames =
+                        FtpFileSystemConfigBuilder.getInstance().getShortMonthNames(fileSystemOptions);
+                if (shortMonthNames != null)
+                {
+                    StringBuffer shortMonthNamesStr = new StringBuffer(BUFSZ);
+                    for (int i = 0; i < shortMonthNames.length; i++)
+                    {
+                        if (shortMonthNamesStr.length() > 0)
+                        {
+                            shortMonthNamesStr.append("|");
+                        }
+                        shortMonthNamesStr.append(shortMonthNames[i]);
+                    }
+                    config.setShortMonthNames(shortMonthNamesStr.toString());
+                }
+
+                client.configure(config);
+            }
+
+            FTPFileEntryParserFactory myFactory =
+                    FtpFileSystemConfigBuilder.getInstance().getEntryParserFactory(fileSystemOptions);
+            if (myFactory != null)
+            {
+                client.setParserFactory(myFactory);
+            }
+
+            try
+            {
+                client.connect(hostname, port);
+
+                int reply = client.getReplyCode();
+                if (!FTPReply.isPositiveCompletion(reply))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/connect-rejected.error", hostname);
+                }
+
+                // Login
+                if (!client.login(
+                    UserAuthenticatorUtils.toString(username),
+                    UserAuthenticatorUtils.toString(password)))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/login.error",
+                            new Object[]{hostname, UserAuthenticatorUtils.toString(username)}, null);
+                }
+
+                // Set binary mode
+                if (!client.setFileType(FTP.BINARY_FILE_TYPE))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/set-binary.error", hostname);
+                }
+
+                // Set dataTimeout value
+                Integer dataTimeout = FtpFileSystemConfigBuilder.getInstance().getDataTimeout(fileSystemOptions);
+                if (dataTimeout != null)
+                {
+                    client.setDataTimeout(dataTimeout.intValue());
+                }
+
+                Integer socketTimeout = FtpFileSystemConfigBuilder.getInstance().getSoTimeout(fileSystemOptions);
+                if (socketTimeout != null)
+                {
+                    client.setSoTimeout(socketTimeout.intValue());
+                }
+
+                // Change to root by default
+                // All file operations a relative to the filesystem-root
+                // String root = getRoot().getName().getPath();
+
+                Boolean userDirIsRoot = FtpFileSystemConfigBuilder.getInstance().getUserDirIsRoot(fileSystemOptions);
+                if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue()))
+                {
+                    if (!client.changeWorkingDirectory(workingDirectory))
+                    {
+                        throw new FileSystemException("vfs.provider.ftp/change-work-directory.error", workingDirectory);
+                    }
+                }
+
+                Boolean passiveMode = FtpFileSystemConfigBuilder.getInstance().getPassiveMode(fileSystemOptions);
+                if (passiveMode != null && passiveMode.booleanValue())
+                {
+                    client.enterLocalPassiveMode();
+                }
+                
+                String controlEncoding = FtpFileSystemConfigBuilder.getInstance().getControlEncoding(fileSystemOptions);
+                if (controlEncoding != null)
+                {
+                    client.setControlEncoding(controlEncoding);
+                }
+                
+                
+            }
+            catch (final IOException e)
+            {
+                if (client.isConnected())
+                {
+                    client.disconnect();
+                }
+                throw e;
+            }
+
+            return client;
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider.ftp/connect.error", new Object[]{hostname}, exc);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileNameParser.java
new file mode 100644
index 0000000..0cc06b7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileNameParser.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.HostFileNameParser;
+
+/**
+ * Implementation for ftp. set default port to 21
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class FtpFileNameParser extends HostFileNameParser
+{
+    private static final FtpFileNameParser INSTANCE = new FtpFileNameParser();
+
+    private static final int PORT = 21;
+
+    public FtpFileNameParser()
+    {
+        super(PORT);
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
new file mode 100644
index 0000000..7aa08ed
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileObject.java
@@ -0,0 +1,752 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileNotFolderException;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.commons.vfs.util.Messages;
+import org.apache.commons.vfs.util.MonitorInputStream;
+import org.apache.commons.vfs.util.MonitorOutputStream;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * An FTP file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FtpFileObject
+    extends AbstractFileObject
+{
+    private static final Map EMPTY_FTP_FILE_MAP = Collections.unmodifiableMap(new TreeMap());
+    private static final FTPFile UNKNOWN = new FTPFile();
+
+    private final Log log = LogFactory.getLog(FtpFileObject.class);
+    private final FtpFileSystem ftpFs;
+    private final String relPath;
+
+    // Cached info
+    private FTPFile fileInfo;
+    private Map children;
+    private FileObject linkDestination;
+
+    private boolean inRefresh;
+
+    protected FtpFileObject(final FileName name,
+                            final FtpFileSystem fileSystem,
+                            final FileName rootName)
+        throws FileSystemException
+    {
+        super(name, fileSystem);
+        ftpFs = fileSystem;
+        String relPath = UriParser.decode(rootName.getRelativeName(name));
+        if (".".equals(relPath))
+        {
+            // do not use the "." as path against the ftp-server
+            // e.g. the uu.net ftp-server do a recursive listing then
+            // this.relPath = UriParser.decode(rootName.getPath());
+            // this.relPath = ".";
+            this.relPath = null;
+        }
+        else
+        {
+            this.relPath = relPath;
+        }
+    }
+
+    /**
+     * Called by child file objects, to locate their ftp file info.
+     *
+     * @param name  the filename in its native form ie. without uri stuff (%nn)
+     * @param flush recreate children cache
+     */
+    private FTPFile getChildFile(final String name, final boolean flush) throws IOException
+    {
+        /* If we should flush cached children, clear our children map unless
+                 * we're in the middle of a refresh in which case we've just recently
+                 * refreshed our children. No need to do it again when our children are
+                 * refresh()ed, calling getChildFile() for themselves from within
+                 * getInfo(). See getChildren(). */
+        if (flush && !inRefresh)
+        {
+            children = null;
+        }
+
+        // List the children of this file
+        doGetChildren();
+
+        // VFS-210
+        if (children == null)
+        {
+            return null;
+        }
+
+        // Look for the requested child
+        FTPFile ftpFile = (FTPFile) children.get(name);
+        return ftpFile;
+    }
+
+    /**
+     * Fetches the children of this file, if not already cached.
+     */
+    private void doGetChildren() throws IOException
+    {
+        if (children != null)
+        {
+            return;
+        }
+
+        final FtpClient client = ftpFs.getClient();
+        try
+        {
+            final String path = fileInfo != null && fileInfo.isSymbolicLink()
+                ? getFileSystem().getFileSystemManager().
+                    resolveName(getParent().getName(), fileInfo.getLink()).getPath()
+                : relPath;
+            final FTPFile[] tmpChildren = client.listFiles(path);
+            if (tmpChildren == null || tmpChildren.length == 0)
+            {
+                children = EMPTY_FTP_FILE_MAP;
+            }
+            else
+            {
+                children = new TreeMap();
+
+                // Remove '.' and '..' elements
+                for (int i = 0; i < tmpChildren.length; i++)
+                {
+                    final FTPFile child = tmpChildren[i];
+                    if (child == null)
+                    {
+                        if (log.isDebugEnabled())
+                        {
+                            log.debug(Messages.getString("vfs.provider.ftp/invalid-directory-entry.debug",
+                                new Object[]
+                                    {
+                                        new Integer(i), relPath
+                                    }));
+                        }
+                        continue;
+                    }
+                    if (!".".equals(child.getName())
+                        && !"..".equals(child.getName()))
+                    {
+                        children.put(child.getName(), child);
+                    }
+                }
+            }
+        }
+        finally
+        {
+            ftpFs.putClient(client);
+        }
+    }
+
+    /**
+     * Attaches this file object to its file resource.
+     */
+    protected void doAttach()
+        throws IOException
+    {
+        // Get the parent folder to find the info for this file
+        // VFS-210 getInfo(false);
+    }
+
+    /**
+     * Fetches the info for this file.
+     */
+    private void getInfo(boolean flush) throws IOException
+    {
+        final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
+        FTPFile newFileInfo;
+        if (parent != null)
+        {
+            newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()), flush);
+        }
+        else
+        {
+            // Assume the root is a directory and exists
+            newFileInfo = new FTPFile();
+            newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
+        }
+
+        if (newFileInfo == null)
+        {
+            this.fileInfo = UNKNOWN;
+        }
+        else
+        {
+            this.fileInfo = newFileInfo;
+        }
+    }
+
+    /**
+     * @throws FileSystemException if an error occurs.
+     */
+    public void refresh() throws FileSystemException
+    {
+        if (!inRefresh)
+        {
+            try
+            {
+                inRefresh = true;
+                super.refresh();
+
+                synchronized (getFileSystem())
+                {
+                    this.fileInfo = null;
+                }
+
+                /* VFS-210
+                try
+                {
+                    // this will tell the parent to recreate its children collection
+                    getInfo(true);
+                }
+                catch (IOException e)
+                {
+                    throw new FileSystemException(e);
+                }
+                */
+            }
+            finally
+            {
+                inRefresh = false;
+            }
+        }
+    }
+
+    /**
+     * Detaches this file object from its file resource.
+     */
+    protected void doDetach()
+    {
+        synchronized (getFileSystem())
+        {
+            this.fileInfo = null;
+            children = null;
+        }
+    }
+
+    /**
+     * Called when the children of this file change.
+     */
+    protected void onChildrenChanged(FileName child, FileType newType)
+    {
+        if (children != null && newType.equals(FileType.IMAGINARY))
+        {
+            try
+            {
+                children.remove(UriParser.decode(child.getBaseName()));
+            }
+            catch (FileSystemException e)
+            {
+                throw new RuntimeException(e.getMessage());
+            }
+        }
+        else
+        {
+            // if child was added we have to rescan the children
+            // TODO - get rid of this
+            children = null;
+        }
+    }
+
+    /**
+     * Called when the type or content of this file changes.
+     */
+    protected void onChange() throws IOException
+    {
+        children = null;
+
+        if (getType().equals(FileType.IMAGINARY))
+        {
+            // file is deleted, avoid server lookup
+            synchronized (getFileSystem())
+            {
+                this.fileInfo = UNKNOWN;
+            }
+            return;
+        }
+
+        getInfo(true);
+    }
+
+    /**
+     * Determines the type of the file, returns null if the file does not
+     * exist.
+     */
+    protected FileType doGetType()
+        throws Exception
+    {
+        // VFS-210
+        synchronized (getFileSystem())
+        {
+            if (this.fileInfo == null)
+            {
+                getInfo(false);
+            }
+
+            if (this.fileInfo == UNKNOWN)
+            {
+                return FileType.IMAGINARY;
+            }
+            else if (this.fileInfo.isDirectory())
+            {
+                return FileType.FOLDER;
+            }
+            else if (this.fileInfo.isFile())
+            {
+                return FileType.FILE;
+            }
+            else if (this.fileInfo.isSymbolicLink())
+            {
+                return getLinkDestination().getType();
+            }
+        }
+
+        throw new FileSystemException("vfs.provider.ftp/get-type.error", getName());
+    }
+
+    private FileObject getLinkDestination() throws FileSystemException
+    {
+        if (linkDestination == null)
+        {
+            final String path;
+            synchronized (getFileSystem())
+            {
+                path = this.fileInfo.getLink();
+            }
+            FileName relativeTo = getName().getParent();
+            if (relativeTo == null)
+            {
+                relativeTo = getName();
+            }
+            FileName linkDestinationName = getFileSystem().getFileSystemManager().resolveName(relativeTo, path);
+            linkDestination = getFileSystem().resolveFile(linkDestinationName);
+        }
+
+        return linkDestination;
+    }
+
+    protected FileObject[] doListChildrenResolved() throws Exception
+    {
+        synchronized (getFileSystem())
+        {
+            if (this.fileInfo != null && this.fileInfo.isSymbolicLink())
+            {
+                return getLinkDestination().getChildren();
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the file's list of children.
+     *
+     * @return The list of children
+     * @throws FileSystemException If there was a problem listing children
+     * @see AbstractFileObject#getChildren()
+     * @since 1.0
+     */
+    public FileObject[] getChildren() throws FileSystemException
+    {
+        try
+        {
+            if (doGetType() != FileType.FOLDER)
+            {
+                throw new FileNotFolderException(getName());
+            }
+        }
+        catch (Exception ex)
+        {
+            throw new FileNotFolderException(getName(), ex);
+        }
+
+
+        try
+        {
+            /* Wrap our parent implementation, noting that we're refreshing so
+             * that we don't refresh() ourselves and each of our parents for
+             * each children. Note that refresh() will list children. Meaning,
+             * if if this file has C children, P parents, there will be (C * P)
+             * listings made with (C * (P + 1)) refreshes, when there should
+             * really only be 1 listing and C refreshes. */
+
+            this.inRefresh = true;
+            return super.getChildren();
+        }
+        finally
+        {
+            this.inRefresh = false;
+        }
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren()
+        throws Exception
+    {
+        // List the children of this file
+        doGetChildren();
+
+        // VFS-210
+        if (children == null)
+        {
+            return null;
+        }
+
+        // TODO - get rid of this children stuff
+        final String[] childNames = new String[children.size()];
+        int childNum = -1;
+        Iterator iterChildren = children.values().iterator();
+        while (iterChildren.hasNext())
+        {
+            childNum++;
+            final FTPFile child = (FTPFile) iterChildren.next();
+            childNames[childNum] = child.getName();
+        }
+
+        return UriParser.encode(childNames);
+    }
+
+    /**
+     * Deletes the file.
+     */
+    protected void doDelete() throws Exception
+    {
+        synchronized (getFileSystem())
+        {
+            final boolean ok;
+            final FtpClient ftpClient = ftpFs.getClient();
+            try
+            {
+                if (this.fileInfo.isDirectory())
+                {
+                    ok = ftpClient.removeDirectory(relPath);
+                }
+                else
+                {
+                    ok = ftpClient.deleteFile(relPath);
+                }
+            }
+            finally
+            {
+                ftpFs.putClient(ftpClient);
+            }
+
+            if (!ok)
+            {
+                throw new FileSystemException("vfs.provider.ftp/delete-file.error", getName());
+            }
+            this.fileInfo = null;
+            children = EMPTY_FTP_FILE_MAP;
+        }
+    }
+
+    /**
+     * Renames the file
+     */
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        synchronized (getFileSystem())
+        {
+            final boolean ok;
+            final FtpClient ftpClient = ftpFs.getClient();
+            try
+            {
+                String oldName = getName().getPath();
+                String newName = newfile.getName().getPath();
+                ok = ftpClient.rename(oldName, newName);
+            }
+            finally
+            {
+                ftpFs.putClient(ftpClient);
+            }
+
+            if (!ok)
+            {
+                throw new FileSystemException("vfs.provider.ftp/rename-file.error",
+                        new Object[]{getName().toString(), newfile});
+            }
+            this.fileInfo = null;
+            children = EMPTY_FTP_FILE_MAP;
+        }
+    }
+
+    /**
+     * Creates this file as a folder.
+     */
+    protected void doCreateFolder()
+        throws Exception
+    {
+        final boolean ok;
+        final FtpClient client = ftpFs.getClient();
+        try
+        {
+            ok = client.makeDirectory(relPath);
+        }
+        finally
+        {
+            ftpFs.putClient(client);
+        }
+
+        if (!ok)
+        {
+            throw new FileSystemException("vfs.provider.ftp/create-folder.error", getName());
+        }
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        synchronized (getFileSystem())
+        {
+            if (this.fileInfo.isSymbolicLink())
+            {
+                return getLinkDestination().getContent().getSize();
+            }
+            else
+            {
+                return this.fileInfo.getSize();
+            }
+        }
+    }
+
+    /**
+     * get the last modified time on an ftp file
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetLastModifiedTime()
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        synchronized (getFileSystem())
+        {
+            if (this.fileInfo.isSymbolicLink())
+            {
+                return getLinkDestination().getContent().getLastModifiedTime();
+            }
+            else
+            {
+                Calendar timestamp = this.fileInfo.getTimestamp();
+                if (timestamp == null)
+                {
+                    return 0L;
+                }
+                else
+                {
+                    return (timestamp.getTime().getTime());
+                }
+            }
+        }
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        final FtpClient client = ftpFs.getClient();
+        try
+        {
+            final InputStream instr = client.retrieveFileStream(relPath);
+            // VFS-210
+            if (instr == null)
+            {
+                throw new FileNotFoundException(getName().toString());
+            }
+            return new FtpInputStream(client, instr);
+        }
+        catch (Exception e)
+        {
+            ftpFs.putClient(client);
+            throw e;
+        }
+    }
+
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        return new FtpRandomAccessContent(this, mode);
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend)
+        throws Exception
+    {
+        final FtpClient client = ftpFs.getClient();
+        try
+        {
+            OutputStream out = null;
+            if (bAppend)
+            {
+                out = client.appendFileStream(relPath);
+            }
+            else
+            {
+                out = client.storeFileStream(relPath);
+            }
+
+            if (out == null)
+            {
+                throw new FileSystemException("vfs.provider.ftp/output-error.debug", new Object[]
+                    {
+                        this.getName(),
+                        client.getReplyString()
+                    });
+            }
+
+            return new FtpOutputStream(client, out);
+        }
+        catch (Exception e)
+        {
+            ftpFs.putClient(client);
+            throw e;
+        }
+    }
+
+    String getRelPath()
+    {
+        return relPath;
+    }
+
+    FtpInputStream getInputStream(long filePointer) throws IOException
+    {
+        final FtpClient client = ftpFs.getClient();
+        try
+        {
+            final InputStream instr = client.retrieveFileStream(relPath, filePointer);
+            if (instr == null)
+            {
+                throw new FileSystemException("vfs.provider.ftp/input-error.debug", new Object[]
+                    {
+                        this.getName(),
+                        client.getReplyString()
+                    });
+            }
+            return new FtpInputStream(client, instr);
+        }
+        catch (IOException e)
+        {
+            ftpFs.putClient(client);
+            throw e;
+        }
+    }
+
+    /**
+     * An InputStream that monitors for end-of-file.
+     */
+    class FtpInputStream
+        extends MonitorInputStream
+    {
+        private final FtpClient client;
+
+        public FtpInputStream(final FtpClient client, final InputStream in)
+        {
+            super(in);
+            this.client = client;
+        }
+
+        void abort() throws IOException
+        {
+            client.abort();
+            close();
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        protected void onClose() throws IOException
+        {
+            final boolean ok;
+            try
+            {
+                ok = client.completePendingCommand();
+            }
+            finally
+            {
+                ftpFs.putClient(client);
+            }
+
+            if (!ok)
+            {
+                throw new FileSystemException("vfs.provider.ftp/finish-get.error", getName());
+            }
+        }
+    }
+
+    /**
+     * An OutputStream that monitors for end-of-file.
+     */
+    private class FtpOutputStream
+        extends MonitorOutputStream
+    {
+        private final FtpClient client;
+
+        public FtpOutputStream(final FtpClient client, final OutputStream outstr)
+        {
+            super(outstr);
+            this.client = client;
+        }
+
+        /**
+         * Called after this stream is closed.
+         */
+        protected void onClose() throws IOException
+        {
+            final boolean ok;
+            try
+            {
+                ok = client.completePendingCommand();
+            }
+            finally
+            {
+                ftpFs.putClient(client);
+            }
+
+            if (!ok)
+            {
+                throw new FileSystemException("vfs.provider.ftp/finish-put.error", getName());
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileProvider.java
new file mode 100644
index 0000000..cf09ca2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileProvider.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A provider for FTP file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FtpFileProvider
+    extends AbstractOriginatingFileProvider
+{
+    /**
+     * File Entry Parser.
+     */
+    public static final String ATTR_FILE_ENTRY_PARSER = "FEP";
+
+    /**
+     * Authenticator types.
+     */
+    public static final UserAuthenticationData.Type[] AUTHENTICATOR_TYPES = new UserAuthenticationData.Type[]
+        {
+            UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD
+        };
+
+    static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.CREATE,
+        Capability.DELETE,
+        Capability.RENAME,
+        Capability.GET_TYPE,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.GET_LAST_MODIFIED,
+        Capability.URI,
+        Capability.WRITE_CONTENT,
+        Capability.APPEND_CONTENT,
+        Capability.RANDOM_ACCESS_READ,
+    }));
+
+    public FtpFileProvider()
+    {
+        super();
+        setFileNameParser(FtpFileNameParser.getInstance());
+    }
+
+    /**
+     * Creates the filesystem.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Create the file system
+        final GenericFileName rootName = (GenericFileName) name;
+
+        FTPClientWrapper ftpClient = new FTPClientWrapper(rootName, fileSystemOptions);
+        /*
+        FTPClient ftpClient = FtpClientFactory.createConnection(rootName.getHostName(),
+            rootName.getPort(),
+            rootName.getUserName(),
+            rootName.getPassword(),
+            rootName.getPath(),
+            fileSystemOptions);
+        */
+
+        return new FtpFileSystem(rootName, ftpClient, fileSystemOptions);
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return FtpFileSystemConfigBuilder.getInstance();
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystem.java
new file mode 100644
index 0000000..fdbc89c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystem.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * An FTP file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FtpFileSystem extends AbstractFileSystem
+{
+    private static final Log LOG = LogFactory.getLog(FtpFileSystem.class);
+
+//    private final String hostname;
+//    private final int port;
+//    private final String username;
+//    private final String password;
+
+    // An idle client
+    private FtpClient idleClient;
+
+    public FtpFileSystem(final GenericFileName rootName, final FtpClient ftpClient, final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+        // hostname = rootName.getHostName();
+        // port = rootName.getPort();
+
+        idleClient = ftpClient;
+    }
+
+    protected void doCloseCommunicationLink()
+    {
+        // Clean up the connection
+        if (idleClient != null)
+        {
+            closeConnection(idleClient);
+            idleClient = null;
+        }
+    }
+
+    /**
+     * Adds the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(FtpFileProvider.capabilities);
+    }
+
+    /**
+     * Cleans up the connection to the server.
+     */
+    private void closeConnection(final FtpClient client)
+    {
+        try
+        {
+            // Clean up
+            if (client.isConnected())
+            {
+                client.disconnect();
+            }
+        }
+        catch (final IOException e)
+        {
+            // getLogger().warn("vfs.provider.ftp/close-connection.error", e);
+            VfsLog.warn(getLogger(), LOG, "vfs.provider.ftp/close-connection.error", e);
+        }
+    }
+
+    /**
+     * Creates an FTP client to use.
+     * @return An FTPCleint.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FtpClient getClient() throws FileSystemException
+    {
+        synchronized (this)
+            {
+                if (idleClient == null || !idleClient.isConnected())
+                {
+                    idleClient = null;
+
+                    return new FTPClientWrapper((GenericFileName) getRoot().getName(), getFileSystemOptions());
+                }
+                else
+                {
+                    final FtpClient client = idleClient;
+                    idleClient = null;
+                    return client;
+                }
+            }
+    }
+
+    /**
+     * Returns an FTP client after use.
+     * @param client The FTPClient.
+     */
+    public void putClient(final FtpClient client)
+    {
+        synchronized (this)
+            {
+                if (idleClient == null)
+                {
+                    // Hang on to client for later
+                    idleClient = client;
+                }
+                else
+                {
+                    // Close the client
+                    closeConnection(client);
+                }
+            }
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name)
+        throws FileSystemException
+    {
+        return new FtpFileObject(name, this, getRootName());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystemConfigBuilder.java
new file mode 100644
index 0000000..dc8e7fe
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpFileSystemConfigBuilder.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * The config BUILDER for various ftp configuration options.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class FtpFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    private static final FtpFileSystemConfigBuilder BUILDER = new FtpFileSystemConfigBuilder();
+
+    private static final String FACTORY_KEY = FTPFileEntryParserFactory.class.getName() + ".KEY";
+    private static final String PASSIVE_MODE = FtpFileSystemConfigBuilder.class.getName() + ".PASSIVE";
+    private static final String USER_DIR_IS_ROOT = FtpFileSystemConfigBuilder.class.getName() + ".USER_DIR_IS_ROOT";
+    private static final String DATA_TIMEOUT = FtpFileSystemConfigBuilder.class.getName() + ".DATA_TIMEOUT";
+    private static final String SO_TIMEOUT = FtpFileSystemConfigBuilder.class.getName() + ".SO_TIMEOUT";
+
+    private static final String SERVER_LANGUAGE_CODE =
+            FtpFileSystemConfigBuilder.class.getName() + ".SERVER_LANGUAGE_CODE";
+    private static final String DEFAULT_DATE_FORMAT =
+            FtpFileSystemConfigBuilder.class.getName() + ".DEFAULT_DATE_FORMAT";
+    private static final String RECENT_DATE_FORMAT =
+            FtpFileSystemConfigBuilder.class.getName() + ".RECENT_DATE_FORMAT";
+    private static final String SERVER_TIME_ZONE_ID =
+            FtpFileSystemConfigBuilder.class.getName() + ".SERVER_TIME_ZONE_ID";
+    private static final String SHORT_MONTH_NAMES =
+            FtpFileSystemConfigBuilder.class.getName() + ".SHORT_MONTH_NAMES";
+    private static final String ENCODING =
+            FtpFileSystemConfigBuilder.class.getName() + ".ENCODING";
+
+    private FtpFileSystemConfigBuilder()
+    {
+        super("ftp.");
+    }
+
+    public static FtpFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * FTPFileEntryParserFactory which will be used for ftp-entry parsing.
+     *
+     * @param opts The FileSystemOptions.
+     * @param factory instance of your factory
+     */
+    public void setEntryParserFactory(FileSystemOptions opts, FTPFileEntryParserFactory factory)
+    {
+        setParam(opts, FTPFileEntryParserFactory.class.getName(), factory);
+    }
+
+    /**
+     * @param opts The FlleSystemOptions.
+     * @see #setEntryParserFactory
+     * @return An FTPFileEntryParserFactory.
+     */
+    public FTPFileEntryParserFactory getEntryParserFactory(FileSystemOptions opts)
+    {
+        return (FTPFileEntryParserFactory) getParam(opts, FTPFileEntryParserFactory.class.getName());
+    }
+
+    /**
+     * set the FQCN of your FileEntryParser used to parse the directory listing from your server.<br />
+     * <br />
+     * <i>If you do not use the default commons-net FTPFileEntryParserFactory e.g. by using
+     * {@link #setEntryParserFactory}
+     * this is the "key" parameter passed as argument into your custom factory</i>
+     *
+     * @param opts The FileSystemOptions.
+     * @param key The key.
+     */
+    public void setEntryParser(FileSystemOptions opts, String key)
+    {
+        setParam(opts, FACTORY_KEY, key);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @see #setEntryParser
+     * @return the key to the EntryParser.
+     */
+    public String getEntryParser(FileSystemOptions opts)
+    {
+        return getString(opts, FACTORY_KEY);
+    }
+
+    protected Class getConfigClass()
+    {
+        return FtpFileSystem.class;
+    }
+
+    /**
+     * enter into passive mode.
+     *
+     * @param opts The FileSystemOptions.
+     * @param passiveMode true if passive mode should be used.
+     */
+    public void setPassiveMode(FileSystemOptions opts, boolean passiveMode)
+    {
+        setParam(opts, PASSIVE_MODE, passiveMode ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @return true if passive mode is set.
+     * @see #setPassiveMode
+     */
+    public Boolean getPassiveMode(FileSystemOptions opts)
+    {
+        return getBoolean(opts, PASSIVE_MODE);
+    }
+
+    /**
+     * use user directory as root (do not change to fs root).
+     *
+     * @param opts The FileSystemOptions.
+     * @param userDirIsRoot true if the user directory should be treated as the root.
+     */
+    public void setUserDirIsRoot(FileSystemOptions opts, boolean userDirIsRoot)
+    {
+        setParam(opts, USER_DIR_IS_ROOT, userDirIsRoot ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @return true if the user directory is treated as the root.
+     * @see #setUserDirIsRoot
+     */
+    public Boolean getUserDirIsRoot(FileSystemOptions opts)
+    {
+        return getBoolean(opts, USER_DIR_IS_ROOT);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @return The timeout as an Integer.
+     * @see #setDataTimeout
+     */
+    public Integer getDataTimeout(FileSystemOptions opts)
+    {
+        return getInteger(opts, DATA_TIMEOUT);
+    }
+
+    /**
+     * set the data timeout for the ftp client.<br />
+     * If you set the dataTimeout to <code>null</code> no dataTimeout will be set on the
+     * ftp client.
+     *
+     * @param opts The FileSystemOptions.
+     * @param dataTimeout The timeout value.
+     */
+    public void setDataTimeout(FileSystemOptions opts, Integer dataTimeout)
+    {
+        setParam(opts, DATA_TIMEOUT, dataTimeout);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return The timeout value.
+     * @see #getDataTimeout
+     */
+    public Integer getSoTimeout(FileSystemOptions opts)
+    {
+        return (Integer) getParam(opts, SO_TIMEOUT);
+    }
+
+    /**
+     * set the socket timeout for the ftp client.<br />
+     * If you set the socketTimeout to <code>null</code> no socketTimeout will be set on the
+     * ftp client.
+     *
+     * @param opts The FileSystem options.
+     * @param soTimeout The timeout value.
+     */
+    public void setSoTimeout(FileSystemOptions opts, Integer soTimeout)
+    {
+        setParam(opts, SO_TIMEOUT, soTimeout);
+    }
+
+    /**
+     * get the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+     * for details and examples.
+     * @param opts The FilesystemOptions.
+     * @return The language code of the server.
+     */
+    public String getServerLanguageCode(FileSystemOptions opts)
+    {
+        return getString(opts, SERVER_LANGUAGE_CODE);
+    }
+
+    /**
+     * set the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+     * for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param serverLanguageCode The servers language code.
+     */
+    public void setServerLanguageCode(FileSystemOptions opts, String serverLanguageCode)
+    {
+        setParam(opts, SERVER_LANGUAGE_CODE, serverLanguageCode);
+    }
+
+    /**
+     * get the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+     * for details and examples.
+     * @param opts The FileSystemOptions
+     * @return The default date format.
+     */
+    public String getDefaultDateFormat(FileSystemOptions opts)
+    {
+        return getString(opts, DEFAULT_DATE_FORMAT);
+    }
+
+    /**
+     * set the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+     * for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param defaultDateFormat The default date format.
+     */
+    public void setDefaultDateFormat(FileSystemOptions opts, String defaultDateFormat)
+    {
+        setParam(opts, DEFAULT_DATE_FORMAT, defaultDateFormat);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @return The recent date format.
+     */
+    public String getRecentDateFormat(FileSystemOptions opts)
+    {
+        return getString(opts, RECENT_DATE_FORMAT);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param recentDateFormat The recent date format.
+     */
+    public void setRecentDateFormat(FileSystemOptions opts, String recentDateFormat)
+    {
+        setParam(opts, RECENT_DATE_FORMAT, recentDateFormat);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @return The server timezone id.
+     */
+    public String getServerTimeZoneId(FileSystemOptions opts)
+    {
+        return getString(opts, SERVER_TIME_ZONE_ID);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param serverTimeZoneId The server timezone id.
+     */
+    public void setServerTimeZoneId(FileSystemOptions opts, String serverTimeZoneId)
+    {
+        setParam(opts, SERVER_TIME_ZONE_ID, serverTimeZoneId);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @return An array of short month names.
+     */
+    public String[] getShortMonthNames(FileSystemOptions opts)
+    {
+        return (String[]) getParam(opts, SHORT_MONTH_NAMES);
+    }
+
+    /**
+     * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param shortMonthNames an array of short month name Strings.
+     */
+    public void setShortMonthNames(FileSystemOptions opts, String[] shortMonthNames)
+    {
+        String[] clone = null;
+        if (shortMonthNames != null)
+        {
+            clone = new String[shortMonthNames.length];
+            System.arraycopy(shortMonthNames, 0, clone, 0, shortMonthNames.length);
+        }
+
+        setParam(opts, SHORT_MONTH_NAMES, clone);
+    }
+    
+    /**
+     * see {@link org.apache.commons.net.ftp.FTP#setControlEncoding} for details and examples.
+     * @param opts The FileSystemOptions.
+     * @param shortMonthNames an array of short month name Strings.
+     */
+    public void setControlEncoding(FileSystemOptions opts, String encoding){
+        setParam(opts, ENCODING, encoding);
+	}
+    
+    public String getControlEncoding(FileSystemOptions opts) {
+        return  (String) getParam(opts, ENCODING);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpRandomAccessContent.java
new file mode 100644
index 0000000..7f394a7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/FtpRandomAccessContent.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractRandomAccessStreamContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.DataInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+
+/**
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class FtpRandomAccessContent extends AbstractRandomAccessStreamContent
+{
+    protected long filePointer;
+
+    private final FtpFileObject fileObject;
+    private DataInputStream dis;
+    private FtpFileObject.FtpInputStream mis;
+
+    FtpRandomAccessContent(final FtpFileObject fileObject, RandomAccessMode mode)
+    {
+        super(mode);
+
+        this.fileObject = fileObject;
+        // fileSystem = (FtpFileSystem) this.fileObject.getFileSystem();
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return filePointer;
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        if (pos == filePointer)
+        {
+            // no change
+            return;
+        }
+
+        if (pos < 0)
+        {
+            throw new FileSystemException("vfs.provider/random-access-invalid-position.error",
+                new Object[]
+                {
+                    new Long(pos)
+                });
+        }
+        if (dis != null)
+        {
+            close();
+        }
+
+        filePointer = pos;
+    }
+
+    protected DataInputStream getDataInputStream() throws IOException
+    {
+        if (dis != null)
+        {
+            return dis;
+        }
+
+        // FtpClient client = fileSystem.getClient();
+        mis = fileObject.getInputStream(filePointer);
+        dis = new DataInputStream(new FilterInputStream(mis)
+        {
+            public int read() throws IOException
+            {
+                int ret = super.read();
+                if (ret > -1)
+                {
+                    filePointer++;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b) throws IOException
+            {
+                int ret = super.read(b);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b, int off, int len) throws IOException
+            {
+                int ret = super.read(b, off, len);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+
+            public void close() throws IOException
+            {
+                FtpRandomAccessContent.this.close();
+            }
+        });
+
+        return dis;
+    }
+
+
+    public void close() throws IOException
+    {
+        if (dis != null)
+        {
+            mis.abort();
+
+            // this is to avoid recursive close
+            DataInputStream oldDis = dis;
+            dis = null;
+            oldDis.close();
+            mis = null;
+        }
+    }
+
+    public long length() throws IOException
+    {
+        return fileObject.getContent().getSize();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/package.html
new file mode 100644
index 0000000..d514a40
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftp/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The FTP File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientFactory.java
new file mode 100644
index 0000000..109f26e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientFactory.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftps;
+
+import org.apache.commons.net.ftp.FTP;
+import org.apache.commons.net.ftp.FTPSClient;
+import org.apache.commons.net.ftp.FTPClientConfig;
+import org.apache.commons.net.ftp.FTPReply;
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+import java.io.IOException;
+
+/**
+ * Create a FtpClient instance
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
+ */
+public class FtpsClientFactory
+{
+    private FtpsClientFactory()
+    {
+    }
+
+    /**
+     * Creates a new connection to the server.
+     */
+    public static FTPSClient createConnection(String hostname, int port, char[] username, char[] password, String workingDirectory, FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        // Determine the username and password to use
+        if (username == null)
+        {
+            username = "anonymous".toCharArray();
+        }
+
+        if (password == null)
+        {
+            password = "anonymous".toCharArray();
+        }
+
+        try
+        {
+            
+            final FTPSClient client;
+          
+            if (FtpsFileSystemConfigBuilder.getInstance().getFtpsType(fileSystemOptions).equals("explicit"))
+              client = new FTPSClient();
+            else if (FtpsFileSystemConfigBuilder.getInstance().getFtpsType(fileSystemOptions).equals("implicit"))
+              client = new FTPSClient(true);
+            else
+              throw new FileSystemException("Invalid FTPS type of "+FtpsFileSystemConfigBuilder.getInstance().getFtpsType(fileSystemOptions)+" specified. Must be 'implicit' or 'explicit'");
+          
+            String key = FtpsFileSystemConfigBuilder.getInstance().getEntryParser(fileSystemOptions);
+            if (key != null)
+            {
+                FTPClientConfig config = new FTPClientConfig(key);
+                
+                String serverLanguageCode = FtpsFileSystemConfigBuilder.getInstance().getServerLanguageCode(fileSystemOptions);
+                if (serverLanguageCode != null)
+                {
+                    config.setServerLanguageCode(serverLanguageCode);
+                }
+                String defaultDateFormat = FtpsFileSystemConfigBuilder.getInstance().getDefaultDateFormat(fileSystemOptions);
+                if (defaultDateFormat != null)
+                {
+                    config.setDefaultDateFormatStr(defaultDateFormat);
+                }
+                String recentDateFormat = FtpsFileSystemConfigBuilder.getInstance().getRecentDateFormat(fileSystemOptions);
+                if (recentDateFormat != null)
+                {
+                    config.setRecentDateFormatStr(recentDateFormat);
+                }
+                String serverTimeZoneId = FtpsFileSystemConfigBuilder.getInstance().getServerTimeZoneId(fileSystemOptions);
+                if (serverTimeZoneId != null)
+                {
+                    config.setServerTimeZoneId(serverTimeZoneId);
+                }
+                String[] shortMonthNames = FtpsFileSystemConfigBuilder.getInstance().getShortMonthNames(fileSystemOptions);
+                if (shortMonthNames != null)
+                {
+                    StringBuffer shortMonthNamesStr = new StringBuffer(40);
+                    for (int i = 0; i<shortMonthNames.length; i++)
+                    {
+                        if (shortMonthNamesStr.length()>0)
+                        {
+                            shortMonthNamesStr.append("|");
+                        }
+                        shortMonthNamesStr.append(shortMonthNames[i]);                        
+                    }
+                    config.setShortMonthNames(shortMonthNamesStr.toString());
+                }
+                
+                client.configure(config);
+            }
+            
+            FTPFileEntryParserFactory myFactory = FtpsFileSystemConfigBuilder.getInstance().getEntryParserFactory(fileSystemOptions);
+            if (myFactory != null)
+            {
+                client.setParserFactory(myFactory);
+            }
+
+            try
+            {
+                client.connect(hostname, port);
+
+                int reply = client.getReplyCode();
+                if (!FTPReply.isPositiveCompletion(reply))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/connect-rejected.error", hostname);
+                }
+
+                // Login
+                if (!client.login(
+                    UserAuthenticatorUtils.toString(username),
+                    UserAuthenticatorUtils.toString(password)))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/login.error", new Object[]{hostname, UserAuthenticatorUtils.toString(username)}, null);
+                }
+
+                // Set binary mode
+                if (!client.setFileType(FTP.BINARY_FILE_TYPE))
+                {
+                    throw new FileSystemException("vfs.provider.ftp/set-binary.error", hostname);
+                }
+
+                // Set dataTimeout value
+                Integer dataTimeout = FtpsFileSystemConfigBuilder.getInstance().getDataTimeout(fileSystemOptions);
+                if (dataTimeout != null)
+                {
+                    client.setDataTimeout(dataTimeout.intValue());
+                }
+
+                // Change to root by default
+                // All file operations a relative to the filesystem-root
+                // String root = getRoot().getName().getPath();
+
+                Boolean userDirIsRoot = FtpsFileSystemConfigBuilder.getInstance().getUserDirIsRoot(fileSystemOptions);
+                if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue()))
+                {
+                    if (!client.changeWorkingDirectory(workingDirectory))
+                    {
+                        throw new FileSystemException("vfs.provider.ftp/change-work-directory.error", workingDirectory);
+                    }
+                }
+
+                Boolean passiveMode = FtpsFileSystemConfigBuilder.getInstance().getPassiveMode(fileSystemOptions);
+                if (passiveMode != null && passiveMode.booleanValue())
+                {
+                    client.enterLocalPassiveMode();
+                }
+            }
+            catch (final IOException e)
+            {
+                if (client.isConnected())
+                {
+                    client.disconnect();
+                }
+                throw e;
+            }
+
+            return client;
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider.ftp/connect.error", new Object[]{hostname}, exc);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientWrapper.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientWrapper.java
new file mode 100644
index 0000000..dd22046
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsClientWrapper.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftps;
+
+
+import org.apache.commons.net.ftp.FTPSClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.vfs.provider.ftp.FtpClient;
+
+
+/**
+ * A wrapper to the FTPClient to allow automatic reconnect on connection loss.<br />
+ * I decided to not to use eg. noop() to determine the state of the connection to avoid unnecesary server round-trips.
+ */
+class FtpsClientWrapper implements FtpClient
+{
+    private final GenericFileName root;
+    private final FileSystemOptions fileSystemOptions;
+
+    private FTPSClient ftpClient = null;
+    
+    FtpsClientWrapper(final GenericFileName root, final FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        this.root = root;
+        this.fileSystemOptions = fileSystemOptions;
+        getFtpsClient(); // fail-fast
+    }
+
+    public GenericFileName getRoot()
+    {
+        return root;
+    }
+
+    public FileSystemOptions getFileSystemOptions()
+    {
+        return fileSystemOptions;
+    }
+
+    private FTPSClient createClient() throws FileSystemException
+    {
+        final GenericFileName rootName = getRoot();
+
+        UserAuthenticationData authData = null;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, FtpsFileProvider.AUTHENTICATOR_TYPES);
+
+            return FtpsClientFactory.createConnection(rootName.getHostName(),
+                rootName.getPort(),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName.getUserName())),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName.getPassword())),
+                rootName.getPath(),
+                getFileSystemOptions());
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+    }
+
+    private FTPSClient getFtpsClient() throws FileSystemException
+    {
+        if (ftpClient == null)
+        {
+            ftpClient = createClient();
+        }
+
+        return ftpClient;
+    }
+
+    public boolean isConnected() throws FileSystemException
+    {
+        return getFtpsClient().isConnected();
+    }
+
+    public void disconnect() throws IOException
+    {
+        try
+        {
+            getFtpsClient().disconnect();
+        }
+        finally
+        {
+            ftpClient = null;
+        }
+    }
+
+    public FTPFile[] listFiles(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().listFiles(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().listFiles(relPath);
+        }
+    }
+
+    public boolean removeDirectory(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().removeDirectory(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().removeDirectory(relPath);
+        }
+    }
+
+    public boolean deleteFile(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().deleteFile(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().deleteFile(relPath);
+        }
+    }
+
+    public boolean rename(String oldName, String newName) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().rename(oldName, newName);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().rename(oldName, newName);
+        }
+    }
+
+    public boolean makeDirectory(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().makeDirectory(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().makeDirectory(relPath);
+        }
+    }
+
+    public boolean completePendingCommand() throws IOException
+    {
+        if (ftpClient != null)
+        {
+            return getFtpsClient().completePendingCommand();
+        }
+
+        return true;
+    }
+
+    public InputStream retrieveFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().retrieveFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().retrieveFileStream(relPath);
+        }
+    }
+
+    public InputStream retrieveFileStream(String relPath, long restartOffset) throws IOException
+    {
+        try
+        {
+            FTPSClient client = getFtpsClient();
+            client.setRestartOffset(restartOffset);
+            return client.retrieveFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+
+            FTPSClient client = getFtpsClient();
+            client.setRestartOffset(restartOffset);
+            return client.retrieveFileStream(relPath);
+        }
+    }
+
+    public OutputStream appendFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().appendFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().appendFileStream(relPath);
+        }
+    }
+
+    public OutputStream storeFileStream(String relPath) throws IOException
+    {
+        try
+        {
+            return getFtpsClient().storeFileStream(relPath);
+        }
+        catch (IOException e)
+        {
+            disconnect();
+            return getFtpsClient().storeFileStream(relPath);
+        }
+    }
+
+    public boolean abort() throws IOException
+    {
+        try
+        {
+            // imario@apache.org: 2005-02-14
+            // it should be better to really "abort" the transfer, but
+            // currently I didnt manage to make it work - so lets "abort" the hard way.
+            // return getFtpsClient().abort();
+
+            disconnect();
+            return true;
+        }
+        catch (IOException e)
+        {
+            disconnect();
+        }
+        return true;
+    }
+
+    public String getReplyString() throws IOException
+    {
+        return getFtpsClient().getReplyString();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileProvider.java
new file mode 100644
index 0000000..d369ec2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileProvider.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftps;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import org.apache.commons.vfs.provider.ftp.FtpFileProvider;
+import org.apache.commons.vfs.provider.ftp.FtpFileSystem;
+
+/**
+ * A provider for FTP file systems.
+ * 
+ * NOTE: Most of the heavy lifting for FTPS is done by the org.apache.commons.vfs.provider.ftp package since 
+ * they both use commons-net package
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
+ */
+public class FtpsFileProvider extends FtpFileProvider
+{
+    public FtpsFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Creates the filesystem.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Create the file system
+        final GenericFileName rootName = (GenericFileName) name;
+
+        FtpsClientWrapper ftpClient = new FtpsClientWrapper(rootName, fileSystemOptions);
+
+        return new FtpFileSystem(rootName, ftpClient, fileSystemOptions);
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return FtpsFileSystemConfigBuilder.getInstance();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileSystemConfigBuilder.java
new file mode 100644
index 0000000..22ff3aa
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/FtpsFileSystemConfigBuilder.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftps;
+
+import org.apache.commons.net.ftp.parser.FTPFileEntryParserFactory;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.ftp.FtpFileSystem;
+
+/**
+ * The config builder for various ftp configuration options
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
+ */
+public class FtpsFileSystemConfigBuilder extends FileSystemConfigBuilder {
+  private final static FtpsFileSystemConfigBuilder builder =
+    new FtpsFileSystemConfigBuilder();
+
+  private final static String FACTORY_KEY =
+    FTPFileEntryParserFactory.class.getName() + ".KEY";
+  private final static String PASSIVE_MODE =
+    FtpsFileSystemConfigBuilder.class.getName() + ".PASSIVE";
+  private final static String USER_DIR_IS_ROOT =
+    FtpsFileSystemConfigBuilder.class.getName() + ".USER_DIR_IS_ROOT";
+  private final static String DATA_TIMEOUT =
+    FtpsFileSystemConfigBuilder.class.getName() + ".DATA_TIMEOUT";
+  private final static String FTPS_TYPE =
+    FtpsFileSystemConfigBuilder.class.getName() + ".FTPS_TYPE";
+
+  private final static String SERVER_LANGUAGE_CODE =
+    FtpsFileSystemConfigBuilder.class.getName() + ".SERVER_LANGUAGE_CODE";
+  private final static String DEFAULT_DATE_FORMAT =
+    FtpsFileSystemConfigBuilder.class.getName() + ".DEFAULT_DATE_FORMAT";
+  private final static String RECENT_DATE_FORMAT =
+    FtpsFileSystemConfigBuilder.class.getName() + ".RECENT_DATE_FORMAT";
+  private final static String SERVER_TIME_ZONE_ID =
+    FtpsFileSystemConfigBuilder.class.getName() + ".SERVER_TIME_ZONE_ID";
+  private final static String SHORT_MONTH_NAMES =
+    FtpsFileSystemConfigBuilder.class.getName() + ".SHORT_MONTH_NAMES";
+
+  public static FtpsFileSystemConfigBuilder getInstance() {
+    return builder;
+  }
+
+  private FtpsFileSystemConfigBuilder() {
+  }
+
+  /**
+   * FTPFileEntryParserFactory which will be used for ftp-entry parsing
+   *
+   * @param opts
+   * @param factory instance of your factory
+   */
+  public void setEntryParserFactory(FileSystemOptions opts,
+                                    FTPFileEntryParserFactory factory) {
+    setParam(opts, FTPFileEntryParserFactory.class.getName(), factory);
+  }
+
+  /**
+   * @param opts
+   * @see #setEntryParserFactory
+   */
+  public FTPFileEntryParserFactory getEntryParserFactory(FileSystemOptions opts) {
+    return (FTPFileEntryParserFactory)getParam(opts,
+                                               FTPFileEntryParserFactory.class.getName());
+  }
+
+  /**
+   * set the FQCN of your FileEntryParser used to parse the directory listing from your server.<br />
+   * <br />
+   * <i>If you do not use the default commons-net FTPFileEntryParserFactory e.g. by using {@link #setEntryParserFactory}
+   * this is the "key" parameter passed as argument into your custom factory</i>
+   *
+   * @param opts
+   * @param key
+   */
+  public void setEntryParser(FileSystemOptions opts, String key) {
+    setParam(opts, FACTORY_KEY, key);
+  }
+
+  /**
+   * @param opts
+   * @see #setEntryParser
+   */
+  public String getEntryParser(FileSystemOptions opts) {
+    return (String)getParam(opts, FACTORY_KEY);
+  }
+
+  protected Class getConfigClass() {
+    return FtpFileSystem.class;
+  }
+
+  /**
+   * enter into passive mode
+   *
+   * @param opts
+   * @param passiveMode
+   */
+  public void setPassiveMode(FileSystemOptions opts, boolean passiveMode) {
+    setParam(opts, PASSIVE_MODE, passiveMode ? Boolean.TRUE : Boolean.FALSE);
+  }
+
+  /**
+   * @param opts
+   * @see #setPassiveMode
+   */
+  public Boolean getPassiveMode(FileSystemOptions opts) {
+    return (Boolean)getParam(opts, PASSIVE_MODE);
+  }
+
+  /**
+   * use user directory as root (do not change to fs root)
+   *
+   * @param opts
+   * @param userDirIsRoot
+   */
+  public void setUserDirIsRoot(FileSystemOptions opts, boolean userDirIsRoot) {
+    setParam(opts, USER_DIR_IS_ROOT,
+             userDirIsRoot ? Boolean.TRUE : Boolean.FALSE);
+  }
+
+  /**
+   * @param opts
+   * @see #setUserDirIsRoot
+   */
+  public Boolean getUserDirIsRoot(FileSystemOptions opts) {
+    return getBoolean(opts, USER_DIR_IS_ROOT, Boolean.TRUE);
+  }
+
+  /**
+   * Set FTPS security mode, either "implicit" or "explicit"
+   *
+   * @param opts
+   * @param ftpsType
+   */
+  public void setFtpsType(FileSystemOptions opts, String ftpsType) {
+    setParam(opts, FTPS_TYPE, ftpsType);
+  }
+
+  /**
+   * Return the FTPS security mode. Defaults to "explicit" if not defined.
+   * @param opts
+   * @see #setFtpsType
+   */
+  public String getFtpsType(FileSystemOptions opts) {
+    return getString(opts, FTPS_TYPE, "explicit");
+  }
+
+  /**
+   * @param opts
+   * @see #setDataTimeout
+   */
+  public Integer getDataTimeout(FileSystemOptions opts) {
+    return (Integer)getParam(opts, DATA_TIMEOUT);
+  }
+
+  /**
+   * set the data timeout for the ftp client.<br />
+   * If you set the dataTimeout to <code>null</code> no dataTimeout will be set on the
+   * ftp client.
+   *
+   * @param opts
+   * @param dataTimeout
+   */
+  public void setDataTimeout(FileSystemOptions opts, Integer dataTimeout) {
+    setParam(opts, DATA_TIMEOUT, dataTimeout);
+  }
+
+  /**
+   * get the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+   * for details and examples.
+   */
+  public String getServerLanguageCode(FileSystemOptions opts) {
+    return (String)getParam(opts, SERVER_LANGUAGE_CODE);
+  }
+
+  /**
+   * set the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+   * for details and examples.
+   */
+  public void setServerLanguageCode(FileSystemOptions opts,
+                                    String serverLanguageCode) {
+    setParam(opts, SERVER_LANGUAGE_CODE, serverLanguageCode);
+  }
+
+  /**
+   * get the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+   * for details and examples.
+   */
+  public String getDefaultDateFormat(FileSystemOptions opts) {
+    return (String)getParam(opts, DEFAULT_DATE_FORMAT);
+  }
+
+  /**
+   * set the language code used by the server. see {@link org.apache.commons.net.ftp.FTPClientConfig}
+   * for details and examples.
+   */
+  public void setDefaultDateFormat(FileSystemOptions opts,
+                                   String defaultDateFormat) {
+    setParam(opts, DEFAULT_DATE_FORMAT, defaultDateFormat);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public String getRecentDateFormat(FileSystemOptions opts) {
+    return (String)getParam(opts, RECENT_DATE_FORMAT);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public void setRecentDateFormat(FileSystemOptions opts,
+                                  String recentDateFormat) {
+    setParam(opts, RECENT_DATE_FORMAT, recentDateFormat);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public String getServerTimeZoneId(FileSystemOptions opts) {
+    return (String)getParam(opts, SERVER_TIME_ZONE_ID);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public void setServerTimeZoneId(FileSystemOptions opts,
+                                  String serverTimeZoneId) {
+    setParam(opts, SERVER_TIME_ZONE_ID, serverTimeZoneId);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public String[] getShortMonthNames(FileSystemOptions opts) {
+    return (String[])getParam(opts, SHORT_MONTH_NAMES);
+  }
+
+  /**
+   * see {@link org.apache.commons.net.ftp.FTPClientConfig} for details and examples.
+   */
+  public void setShortMonthNames(FileSystemOptions opts,
+                                 String[] shortMonthNames) {
+    String[] clone = null;
+    if (shortMonthNames != null) {
+      clone = new String[shortMonthNames.length];
+      System.arraycopy(shortMonthNames, 0, clone, 0, shortMonthNames.length);
+    }
+
+    setParam(opts, SHORT_MONTH_NAMES, clone);
+  }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/package.html
new file mode 100644
index 0000000..025c6a4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ftps/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The FTPS File Provider.</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileObject.java
new file mode 100644
index 0000000..e2b0f51
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileObject.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.gzip;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileObject;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileSystem;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * the gzip file.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class GzipFileObject extends CompressedFileFileObject
+{
+    protected GzipFileObject(FileName name, FileObject container, CompressedFileFileSystem fs)
+    {
+        super(name, container, fs);
+    }
+
+    protected InputStream doGetInputStream() throws Exception
+    {
+        InputStream is = getContainer().getContent().getInputStream();
+        return new GZIPInputStream(is);
+    }
+
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        OutputStream os = getContainer().getContent().getOutputStream(false);
+        return new GZIPOutputStream(os);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileProvider.java
new file mode 100644
index 0000000..4618021
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileProvider.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.gzip;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileProvider;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Provides access to the content of gzip compressed files.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class GzipFileProvider extends CompressedFileFileProvider
+{
+    /**
+     * Capabilities.
+     */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.GET_LAST_MODIFIED,
+        Capability.GET_TYPE,
+        Capability.LIST_CHILDREN,
+        Capability.WRITE_CONTENT,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.COMPRESS
+    }));
+
+    public GzipFileProvider()
+    {
+        super();
+    }
+
+    protected FileSystem createFileSystem(FileName name, FileObject file, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        return new GzipFileSystem(name, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileSystem.java
new file mode 100644
index 0000000..f8e3cc6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/GzipFileSystem.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.gzip;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.compressed.CompressedFileFileSystem;
+
+import java.util.Collection;
+
+/**
+ * Filesytem to handle compressed files using the gzip method.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class GzipFileSystem extends CompressedFileFileSystem
+{
+    protected GzipFileSystem(FileName rootName, FileObject parentLayer, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+    }
+
+    protected FileObject createFile(FileName name) throws FileSystemException
+    {
+        return new GzipFileObject(name, getParentLayer(), this);
+    }
+
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(GzipFileProvider.capabilities);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/package.html
new file mode 100644
index 0000000..6a8fa03
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/gzip/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The GZIP File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpClientFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpClientFactory.java
new file mode 100644
index 0000000..adcbffd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpClientFactory.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+import org.apache.commons.httpclient.params.HttpClientParams;
+import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+/**
+ * Create a HttpClient instance.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class HttpClientFactory
+{
+    private HttpClientFactory()
+    {
+    }
+
+    public static HttpClient createConnection(String scheme, String hostname, int port, String username,
+                                              String password, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        return createConnection(HttpFileSystemConfigBuilder.getInstance(), scheme, hostname, port,
+            username, password, fileSystemOptions);
+    }
+
+    /**
+     * Creates a new connection to the server.
+     * @param builder The HttpFileSystemConfigBuilder.
+     * @param scheme The protocol.
+     * @param hostname The hostname.
+     * @param port The port number.
+     * @param username The username.
+     * @param password The password
+     * @param fileSystemOptions The file system options.
+     * @return a new HttpClient connection.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static HttpClient createConnection(HttpFileSystemConfigBuilder builder, String scheme,
+                                              String hostname, int port, String username,
+                                              String password, FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        HttpClient client;
+        try
+        {
+            HttpConnectionManager mgr = new MultiThreadedHttpConnectionManager();
+            HttpConnectionManagerParams connectionMgrParams = mgr.getParams();
+
+            client = new HttpClient(mgr);
+
+            final HostConfiguration config = new HostConfiguration();
+            config.setHost(hostname, port, scheme);
+
+            if (fileSystemOptions != null)
+            {
+                String proxyHost = builder.getProxyHost(fileSystemOptions);
+                int proxyPort = builder.getProxyPort(fileSystemOptions);
+
+                if (proxyHost != null && proxyHost.length() > 0 && proxyPort > 0)
+                {
+                    config.setProxy(proxyHost, proxyPort);
+                }
+
+                UserAuthenticator proxyAuth = builder.getProxyAuthenticator(fileSystemOptions);
+                if (proxyAuth != null)
+                {
+                    UserAuthenticationData authData = UserAuthenticatorUtils.authenticate(proxyAuth,
+                        new UserAuthenticationData.Type[]
+                        {
+                            UserAuthenticationData.USERNAME,
+                            UserAuthenticationData.PASSWORD
+                        });
+
+                    if (authData != null)
+                    {
+                        final UsernamePasswordCredentials proxyCreds =
+                            new UsernamePasswordCredentials(
+                                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                                    UserAuthenticationData.USERNAME, null)),
+                                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                                    UserAuthenticationData.PASSWORD, null)));
+
+                        client.getState().setProxyCredentials(null, proxyHost, proxyCreds);
+                    }
+
+                    if (builder.isPreemptiveAuth(fileSystemOptions)) {
+	                    HttpClientParams httpClientParams = new HttpClientParams();
+	                    httpClientParams.setAuthenticationPreemptive(true);
+	                    client.setParams(httpClientParams);
+                    }
+                }
+
+                Cookie[] cookies = builder.getCookies(fileSystemOptions);
+                if (cookies != null)
+                {
+                    client.getState().addCookies(cookies);
+                }
+            }
+            /**
+             * ConnectionManager set methodsmust be called after the host & port and proxy host & port
+             * are set in the HostConfiguration. They are all used as part of the key when HttpConnectionManagerParams
+             * tries to locate the host configuration.
+             */
+            connectionMgrParams.setMaxConnectionsPerHost(config, builder.getMaxConnectionsPerHost(fileSystemOptions));
+            connectionMgrParams.setMaxTotalConnections(builder.getMaxTotalConnections(fileSystemOptions));
+
+            client.setHostConfiguration(config);
+
+            if (username != null)
+            {
+                final UsernamePasswordCredentials creds =
+                    new UsernamePasswordCredentials(username, password);
+                client.getState().setCredentials(null, hostname, creds);
+            }
+
+            client.executeMethod(new HeadMethod());
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider.http/connect.error", new Object[]{hostname}, exc);
+        }
+
+        return client;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileContentInfoFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileContentInfoFactory.java
new file mode 100644
index 0000000..cd4ba1a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileContentInfoFactory.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HeaderElement;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.DefaultFileContentInfo;
+import org.apache.commons.vfs.util.FileObjectUtils;
+
+/**
+ * Creates the FileContentInfo.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpFileContentInfoFactory implements FileContentInfoFactory
+{
+    public FileContentInfo create(FileContent fileContent) throws FileSystemException
+    {
+        HttpFileObject httpFile = (HttpFileObject) (FileObjectUtils
+            .getAbstractFileObject(fileContent.getFile()));
+
+        String contentType = null;
+        String contentEncoding = null;
+
+        Header header = httpFile.getHeadMethod().getResponseHeader("content-type");
+        if (header != null)
+        {
+            HeaderElement[] element;
+            try
+            {
+                element = header.getValues();
+            }
+            catch (HttpException e)
+            {
+                throw new FileSystemException(e);
+            }
+            if (element != null && element.length > 0)
+            {
+                contentType = element[0].getName();
+            }
+        }
+
+        contentEncoding = httpFile.getHeadMethod().getResponseCharSet();
+
+        return new DefaultFileContentInfo(contentType, contentEncoding);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileNameParser.java
new file mode 100644
index 0000000..66902e4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileNameParser.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+
+/**
+ * Implementation for http. set default port to 80
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$
+ */
+public class HttpFileNameParser extends URLFileNameParser
+{
+    private static final HttpFileNameParser INSTANCE = new HttpFileNameParser();
+
+    public HttpFileNameParser()
+    {
+        super(80);
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileObject.java
new file mode 100644
index 0000000..71189fb
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileObject.java
@@ -0,0 +1,246 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.httpclient.util.DateParser;
+import org.apache.commons.httpclient.util.URIUtil;
+
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.util.MonitorInputStream;
+import org.apache.commons.vfs.util.RandomAccessMode;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileNotFoundException;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.FileContentInfoFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+
+/**
+ * A file object backed by commons httpclient.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo status codes
+ */
+public class HttpFileObject
+    extends AbstractFileObject
+{
+    private final HttpFileSystem fileSystem;
+    private final String urlCharset;
+    private HeadMethod method;
+
+    protected HttpFileObject(final FileName name,
+                             final HttpFileSystem fileSystem)
+    {
+        super(name, fileSystem);
+        this.fileSystem = fileSystem;
+        urlCharset = HttpFileSystemConfigBuilder.getInstance().getUrlCharset(getFileSystem().getFileSystemOptions());
+    }
+
+    /**
+     * Detaches this file object from its file resource.
+     */
+    protected void doDetach()
+        throws Exception
+    {
+        method = null;
+    }
+
+    /**
+     * Determines the type of this file.  Must not return null.  The return
+     * value of this method is cached, so the implementation can be expensive.
+     */
+    protected FileType doGetType()
+        throws Exception
+    {
+        // Use the HEAD method to probe the file.
+        method = new HeadMethod();
+        setupMethod(method);
+        final HttpClient client = fileSystem.getClient();
+        final int status = client.executeMethod(method);
+        method.releaseConnection();
+        if (status == HttpURLConnection.HTTP_OK)
+        {
+            return FileType.FILE;
+        }
+        else if (status == HttpURLConnection.HTTP_NOT_FOUND
+            || status == HttpURLConnection.HTTP_GONE)
+        {
+            return FileType.IMAGINARY;
+        }
+        else
+        {
+            throw new FileSystemException("vfs.provider.http/head.error", getName());
+        }
+    }
+
+    /**
+     * Lists the children of this file.
+     */
+    protected String[] doListChildren()
+        throws Exception
+    {
+        throw new Exception("Not implemented.");
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize()
+        throws Exception
+    {
+        final Header header = method.getResponseHeader("content-length");
+        if (header == null)
+        {
+            // Assume 0 content-length
+            return 0;
+        }
+        return Long.parseLong(header.getValue());
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected long doGetLastModifiedTime()
+        throws Exception
+    {
+        final Header header = method.getResponseHeader("last-modified");
+        if (header == null)
+        {
+            throw new FileSystemException("vfs.provider.http/last-modified.error", getName());
+        }
+        return DateParser.parseDate(header.getValue()).getTime();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.  Is only called
+     * if {@link #doGetType} returns {@link FileType#FILE}.
+     * <p/>
+     * <p>It is guaranteed that there are no open output streams for this file
+     * when this method is called.
+     * <p/>
+     * <p>The returned stream does not have to be buffered.
+     */
+    protected InputStream doGetInputStream()
+        throws Exception
+    {
+        final GetMethod getMethod = new GetMethod();
+        setupMethod(getMethod);
+        final int status = fileSystem.getClient().executeMethod(getMethod);
+        if (status == HttpURLConnection.HTTP_NOT_FOUND)
+        {
+            throw new FileNotFoundException(getName());
+        }
+        if (status != HttpURLConnection.HTTP_OK)
+        {
+            throw new FileSystemException("vfs.provider.http/get.error", getName());
+        }
+
+        return new HttpInputStream(getMethod);
+    }
+
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        return new HttpRandomAccessContent(this, mode);
+    }
+
+    /**
+     * Prepares a Method object.
+     */
+    protected void setupMethod(final HttpMethod method) throws FileSystemException, URIException
+    {
+        String pathEncoded = ((URLFileName) getName()).getPathQueryEncoded(urlCharset);
+        method.setPath(pathEncoded);
+        method.setFollowRedirects(true);
+        method.setRequestHeader("User-Agent", "Jakarta-Commons-VFS");
+    }
+
+    protected String encodePath(final String decodedPath) throws URIException
+    {
+        String pathEncoded = URIUtil.encodePath(decodedPath);
+        return pathEncoded;
+    }
+
+    /**
+     * An InputStream that cleans up the HTTP connection on close.
+     */
+    static class HttpInputStream
+        extends MonitorInputStream
+    {
+        private final GetMethod method;
+
+        public HttpInputStream(final GetMethod method)
+            throws IOException
+        {
+            super(method.getResponseBodyAsStream());
+            this.method = method;
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        protected void onClose()
+            throws IOException
+        {
+            method.releaseConnection();
+        }
+    }
+
+
+    protected FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return new HttpFileContentInfoFactory();
+    }
+
+    HeadMethod getHeadMethod()
+    {
+        return method;
+    }
+
+    /*
+    protected Map doGetAttributes() throws Exception
+    {
+        TreeMap map = new TreeMap();
+
+        Header contentType = method.getResponseHeader("content-type");
+        if (contentType != null)
+        {
+            HeaderElement[] element = contentType.getValues();
+            if (element != null && element.length > 0)
+            {
+                map.put("content-type", element[0].getName());
+            }
+        }
+
+        map.put("content-encoding", method.getResponseCharSet());
+        return map;
+    }
+    */
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileProvider.java
new file mode 100644
index 0000000..f053d7c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileProvider.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.GenericFileName;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+
+/**
+ * An HTTP provider that uses commons-httpclient.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpFileProvider
+    extends AbstractOriginatingFileProvider
+{
+    /** Authenticator information. */
+    public static final UserAuthenticationData.Type[] AUTHENTICATOR_TYPES = new UserAuthenticationData.Type[]
+        {
+            UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD
+        };
+
+    static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.GET_TYPE,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.GET_LAST_MODIFIED,
+        Capability.ATTRIBUTES,
+        Capability.RANDOM_ACCESS_READ,
+        Capability.DIRECTORY_READ_CONTENT,
+    }));
+
+    public HttpFileProvider()
+    {
+        super();
+        setFileNameParser(HttpFileNameParser.getInstance());
+    }
+
+    /**
+     * Creates a {@link FileSystem}.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Create the file system
+        final GenericFileName rootName = (GenericFileName) name;
+
+        UserAuthenticationData authData = null;
+        HttpClient httpClient;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, AUTHENTICATOR_TYPES);
+
+            httpClient = HttpClientFactory.createConnection(
+                rootName.getScheme(),
+                rootName.getHostName(),
+                rootName.getPort(),
+                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                    UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName.getUserName()))),
+                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                    UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName.getPassword()))),
+                fileSystemOptions);
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+
+        return new HttpFileSystem(rootName, httpClient, fileSystemOptions);
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return HttpFileSystemConfigBuilder.getInstance();
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystem.java
new file mode 100644
index 0000000..47b8b64
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystem.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.util.Collection;
+
+/**
+ * An HTTP file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    private final HttpClient client;
+
+    protected HttpFileSystem(final GenericFileName rootName, final HttpClient client,
+                             final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+        this.client = client;
+    }
+
+    /**
+     * Adds the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(HttpFileProvider.capabilities);
+    }
+
+    protected HttpClient getClient()
+    {
+        return client;
+    }
+
+    public void closeCommunicationLink()
+    {
+        if (getClient() != null)
+        {
+            HttpConnectionManager mgr = getClient().getHttpConnectionManager();
+            if (mgr instanceof ThreadLocalHttpConnectionManager)
+            {
+                ((ThreadLocalHttpConnectionManager) mgr).releaseLocalConnection();
+            }
+            if (mgr instanceof MultiThreadedHttpConnectionManager)
+            {
+                ((MultiThreadedHttpConnectionManager) mgr).shutdown();
+            }
+        }
+    }
+
+    /**
+     * Creates a file object.  This method is called only if the requested
+     * file is not cached.
+     */
+    protected FileObject createFile(final FileName name)
+        throws Exception
+    {
+        return new HttpFileObject(name, this);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystemConfigBuilder.java
new file mode 100644
index 0000000..f9f3a91
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpFileSystemConfigBuilder.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.httpclient.Cookie;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+
+/**
+ * Configuration options for HTTP.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    private static final HttpFileSystemConfigBuilder BUILDER = new HttpFileSystemConfigBuilder();
+
+    private static final int DEFAULT_MAX_HOST_CONNECTIONS = 5;
+
+    private static final int DEFAULT_MAX_CONNECTIONS = 50;
+    
+    private static final String OPTION_NAME__PREEMPTIVE_AUTHENTICATION = "preemptiveAuth";
+    
+	protected HttpFileSystemConfigBuilder(String prefix)
+    {
+        super(prefix);
+    }
+
+    private HttpFileSystemConfigBuilder()
+    {
+        super("http.");
+    }
+
+    public static HttpFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * Set the charset used for url encoding.<br>
+     *
+     * @param opts The FileSystem options.
+     * @param chaset the chaset
+     */
+    public void setUrlCharset(FileSystemOptions opts, String chaset)
+    {
+        setParam(opts, "urlCharset", chaset);
+    }
+
+    /**
+     * Set the charset used for url encoding.<br>
+     *
+     * @param opts The FileSystem options.
+     * @return the chaset
+     */
+    public String getUrlCharset(FileSystemOptions opts)
+    {
+        return getString(opts, "urlCharset");
+    }
+
+    /**
+     * Set the proxy to use for http connection.<br>
+     * You have to set the ProxyPort too if you would like to have the proxy really used.
+     *
+     * @param opts The FileSystem options.
+     * @param proxyHost the host
+     * @see #setProxyPort
+     */
+    public void setProxyHost(FileSystemOptions opts, String proxyHost)
+    {
+        setParam(opts, "proxyHost", proxyHost);
+    }
+
+    /**
+     * Set the proxy-port to use for http connection.
+     * You have to set the ProxyHost too if you would like to have the proxy really used.
+     *
+     * @param opts The FileSystem options.
+     * @param proxyPort the port
+     * @see #setProxyHost
+     */
+    public void setProxyPort(FileSystemOptions opts, int proxyPort)
+    {
+        setParam(opts, "proxyPort", new Integer(proxyPort));
+    }
+
+    /**
+     * Get the proxy to use for http connection.
+     * You have to set the ProxyPort too if you would like to have the proxy really used.
+     *
+     * @param opts The FileSystem options.
+     * @return proxyHost
+     * @see #setProxyPort
+     */
+    public String getProxyHost(FileSystemOptions opts)
+    {
+        return getString(opts, "proxyHost");
+    }
+
+    /**
+     * Get the proxy-port to use for http the connection.
+     * You have to set the ProxyHost too if you would like to have the proxy really used.
+     *
+     * @param opts The FileSystem options.
+     * @return proxyPort: the port number or 0 if it is not set
+     * @see #setProxyHost
+     */
+    public int getProxyPort(FileSystemOptions opts)
+    {
+        return getInteger(opts, "proxyPort", 0);
+    }
+
+    /**
+     * Set the proxy authenticator where the system should get the credentials from.
+     * @param opts The FileSystem options.
+     * @param authenticator The UserAuthenticator.
+     */
+    public void setProxyAuthenticator(FileSystemOptions opts, UserAuthenticator authenticator)
+    {
+        setParam(opts, "proxyAuthenticator", authenticator);
+    }
+
+    /**
+     * Get the proxy authenticator where the system should get the credentials from.
+     * @param opts The FileSystem options.
+     * @return The UserAuthenticator.
+     */
+    public UserAuthenticator getProxyAuthenticator(FileSystemOptions opts)
+    {
+        return (UserAuthenticator) getParam(opts, "proxyAuthenticator");
+    }
+
+    /**
+     * The cookies to add to the request.
+     * @param opts The FileSystem options.
+     * @param cookies An array of Cookies.
+     */
+    public void setCookies(FileSystemOptions opts, Cookie[] cookies)
+    {
+        setParam(opts, "cookies", cookies);
+    }
+
+    /**
+     * The cookies to add to the request.
+     * @param opts The FileSystem options.
+     * @return the Cookie array.
+     */
+    public Cookie[] getCookies(FileSystemOptions opts)
+    {
+        return (Cookie[]) getParam(opts, "cookies");
+    }
+
+    /**
+     * The maximum number of connections allowed.
+     * @param opts The FileSystem options.
+     * @param maxTotalConnections The maximum number of connections.
+     */
+    public void setMaxTotalConnections(FileSystemOptions opts, int maxTotalConnections)
+    {
+        setParam(opts, HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, new Integer(maxTotalConnections));
+    }
+
+    /**
+     * Retrieve the maximum number of connections allowed.
+     * @param opts The FileSystemOptions.
+     * @return The maximum number of connections allowed.
+     */
+    public int getMaxTotalConnections(FileSystemOptions opts)
+    {
+        return getInteger(opts, HttpConnectionManagerParams.MAX_TOTAL_CONNECTIONS, DEFAULT_MAX_CONNECTIONS);
+    }
+
+    /**
+     * The maximum number of connections allowed to any host.
+     * @param opts The FileSystem options.
+     * @param maxHostConnections The maximum number of connections to a host.
+     */
+    public void setMaxConnectionsPerHost(FileSystemOptions opts, int maxHostConnections)
+    {
+        setParam(opts, HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, new Integer(maxHostConnections));
+    }
+
+    /**
+     * Retrieve the maximum number of connections allowed per host.
+     * @param opts The FileSystemOptions.
+     * @return The maximum number of connections allowed per host.
+     */
+    public int getMaxConnectionsPerHost(FileSystemOptions opts)
+    {
+        return getInteger(opts, HttpConnectionManagerParams.MAX_HOST_CONNECTIONS, DEFAULT_MAX_HOST_CONNECTIONS);
+    }
+
+    /**
+     * Determines if the FileSystemOptions indicate that preemptive 
+     * authentication is requested.
+     * @param opts The FileSystemOptions.
+     * @return true if preemptiveAuth is requested.
+     */
+    public boolean isPreemptiveAuth(FileSystemOptions opts) {
+		return getBoolean(opts, OPTION_NAME__PREEMPTIVE_AUTHENTICATION, Boolean.FALSE).booleanValue();
+	}
+
+    /**
+     * Sets the given value for preemptive HTTP authentication (using BASIC) on the
+     * given FileSystemOptions object.  Defaults to false if not set.  It may be 
+     * appropriate to set to true in cases when the resulting chattiness of the 
+     * conversation outweighs any architectural desire to use a stronger authentication
+     * scheme than basic/preemptive.
+     * @param opts The FileSystemOptions.
+     * @param preemptiveAuth the desired setting; true=enabled and false=disabled.
+     */
+	public void setPreemptiveAuth(FileSystemOptions opts, boolean preemptiveAuth) {
+		setParam(opts, OPTION_NAME__PREEMPTIVE_AUTHENTICATION, Boolean.valueOf(preemptiveAuth));
+	}
+
+	protected Class getConfigClass()
+    {
+        return HttpFileSystem.class;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpRandomAccessContent.java
new file mode 100644
index 0000000..5cad685
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/HttpRandomAccessContent.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractRandomAccessStreamContent;
+import org.apache.commons.vfs.util.MonitorInputStream;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.DataInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+
+/**
+ * RandomAccess content using Http.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class HttpRandomAccessContent extends AbstractRandomAccessStreamContent
+{
+    protected long filePointer = 0;
+
+    private final HttpFileObject fileObject;
+    private final HttpFileSystem fileSystem;
+
+    private DataInputStream dis = null;
+    private MonitorInputStream mis = null;
+
+    HttpRandomAccessContent(final HttpFileObject fileObject, RandomAccessMode mode)
+    {
+        super(mode);
+
+        this.fileObject = fileObject;
+        fileSystem = (HttpFileSystem) this.fileObject.getFileSystem();
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return filePointer;
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        if (pos == filePointer)
+        {
+            // no change
+            return;
+        }
+
+        if (pos < 0)
+        {
+            throw new FileSystemException("vfs.provider/random-access-invalid-position.error",
+                new Object[]
+                {
+                    new Long(pos)
+                });
+        }
+        if (dis != null)
+        {
+            close();
+        }
+
+        filePointer = pos;
+    }
+
+    protected DataInputStream getDataInputStream() throws IOException
+    {
+        if (dis != null)
+        {
+            return dis;
+        }
+
+        final GetMethod getMethod = new GetMethod();
+        fileObject.setupMethod(getMethod);
+        getMethod.setRequestHeader("Range", "bytes=" + filePointer + "-");
+        final int status = fileSystem.getClient().executeMethod(getMethod);
+        if (status != HttpURLConnection.HTTP_PARTIAL && status != HttpURLConnection.HTTP_OK)
+        {
+            throw new FileSystemException("vfs.provider.http/get-range.error", new Object[]
+            {
+                fileObject.getName(),
+                new Long(filePointer)
+            });
+        }
+
+        mis = new HttpFileObject.HttpInputStream(getMethod);
+        // If the range request was ignored
+        if (status == HttpURLConnection.HTTP_OK)
+        {
+            long skipped = mis.skip(filePointer);
+            if (skipped != filePointer)
+            {
+                throw new FileSystemException("vfs.provider.http/get-range.error", new Object[]
+                {
+                    fileObject.getName(),
+                    new Long(filePointer)
+                });
+            }
+        }
+        dis = new DataInputStream(new FilterInputStream(mis)
+        {
+            public int read() throws IOException
+            {
+                int ret = super.read();
+                if (ret > -1)
+                {
+                    filePointer++;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b) throws IOException
+            {
+                int ret = super.read(b);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b, int off, int len) throws IOException
+            {
+                int ret = super.read(b, off, len);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+        });
+
+        return dis;
+    }
+
+
+    public void close() throws IOException
+    {
+        if (dis != null)
+        {
+            dis.close();
+            dis = null;
+            mis = null;
+        }
+    }
+
+    public long length() throws IOException
+    {
+        return fileObject.getContent().getSize();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/ThreadLocalHttpConnectionManager.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/ThreadLocalHttpConnectionManager.java
new file mode 100644
index 0000000..317936b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/ThreadLocalHttpConnectionManager.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http;
+
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.commons.httpclient.HttpConnection;
+import org.apache.commons.httpclient.HttpConnectionManager;
+import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A connection manager that provides access to a single HttpConnection.  This
+ * manager makes no attempt to provide exclusive access to the contained
+ * HttpConnection.
+ * <p/>
+ * imario@apache.org: Keep connection in ThreadLocal.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
+ * @author Eric Johnson
+ * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
+ * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
+ * @author Laura Werner
+ * @since 2.0
+ */
+public class ThreadLocalHttpConnectionManager implements HttpConnectionManager
+{
+    /**
+     * The thread data.
+     */
+    protected ThreadLocal localHttpConnection = new ThreadLocal()
+    {
+        protected Object initialValue()
+        {
+            return new Entry();
+        }
+    };
+
+    /**
+     * Collection of parameters associated with this connection manager.
+     */
+    private HttpConnectionManagerParams params = new HttpConnectionManagerParams();
+
+
+    public ThreadLocalHttpConnectionManager()
+    {
+    }
+
+    /**
+     * Since the same connection is about to be reused, make sure the
+     * previous request was completely processed, and if not
+     * consume it now.
+     *
+     * @param conn The connection
+     */
+    static void finishLastResponse(HttpConnection conn)
+    {
+        InputStream lastResponse = conn.getLastResponseInputStream();
+        if (lastResponse != null)
+        {
+            conn.setLastResponseInputStream(null);
+            try
+            {
+                lastResponse.close();
+            }
+            catch (IOException ioe)
+            {
+                //FIXME: badness - close to force reconnect.
+                conn.close();
+            }
+        }
+    }
+
+    /**
+     * release the connection of the current thread.
+     */
+    public void releaseLocalConnection()
+    {
+        if (getLocalHttpConnection() != null)
+        {
+            releaseConnection(getLocalHttpConnection());
+        }
+    }
+
+    /**
+     * A connection entry.
+     */
+    private static class Entry
+    {
+        /**
+         * The http connection.
+         */
+        private HttpConnection conn = null;
+
+        /**
+         * The time the connection was made idle.
+         */
+        private long idleStartTime = Long.MAX_VALUE;
+
+        private Entry()
+        {
+        }
+    }
+
+    protected HttpConnection getLocalHttpConnection()
+    {
+        return ((Entry) localHttpConnection.get()).conn;
+    }
+
+    protected void setLocalHttpConnection(HttpConnection conn)
+    {
+        ((Entry) localHttpConnection.get()).conn = conn;
+    }
+
+    protected long getIdleStartTime()
+    {
+        return ((Entry) localHttpConnection.get()).idleStartTime;
+    }
+
+    protected void setIdleStartTime(long idleStartTime)
+    {
+        ((Entry) localHttpConnection.get()).idleStartTime = idleStartTime;
+    }
+
+    /**
+     * @param hostConfiguration The host configuration.
+     * @return the HttpConnection.
+     * @see HttpConnectionManager#getConnection(org.apache.commons.httpclient.HostConfiguration)
+     */
+    public HttpConnection getConnection(HostConfiguration hostConfiguration)
+    {
+        return getConnection(hostConfiguration, 0);
+    }
+
+    /**
+     * Gets the staleCheckingEnabled value to be set on HttpConnections that are created.
+     *
+     * @return <code>true</code> if stale checking will be enabled on HttpConections
+     * @see HttpConnection#isStaleCheckingEnabled()
+     */
+    public boolean isConnectionStaleCheckingEnabled()
+    {
+        return this.params.isStaleCheckingEnabled();
+    }
+
+    /**
+     * Sets the staleCheckingEnabled value to be set on HttpConnections that are created.
+     *
+     * @param connectionStaleCheckingEnabled <code>true</code> if stale checking will be enabled
+     *                                       on HttpConections
+     * @see HttpConnection#setStaleCheckingEnabled(boolean)
+     */
+    public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled)
+    {
+        this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled);
+    }
+
+    /**
+     * @param hostConfiguration The host configuration.
+     * @param timeout The timeout value.
+     * @return The HttpConnection.
+     * @see HttpConnectionManager#getConnection(HostConfiguration, long)
+     * @since 3.0
+     */
+    public HttpConnection getConnectionWithTimeout(
+        HostConfiguration hostConfiguration, long timeout)
+    {
+
+        HttpConnection httpConnection = getLocalHttpConnection();
+        if (httpConnection == null)
+        {
+            httpConnection = new HttpConnection(hostConfiguration);
+            setLocalHttpConnection(httpConnection);
+            httpConnection.setHttpConnectionManager(this);
+            httpConnection.getParams().setStaleCheckingEnabled(params.isStaleCheckingEnabled());
+        }
+        else
+        {
+
+            // make sure the host and proxy are correct for this connection
+            // close it and set the values if they are not
+            if (!hostConfiguration.hostEquals(httpConnection)
+                || !hostConfiguration.proxyEquals(httpConnection))
+            {
+
+                if (httpConnection.isOpen())
+                {
+                    httpConnection.close();
+                }
+
+                httpConnection.setHost(hostConfiguration.getHost());
+                httpConnection.setPort(hostConfiguration.getPort());
+                httpConnection.setProtocol(hostConfiguration.getProtocol());
+                httpConnection.setLocalAddress(hostConfiguration.getLocalAddress());
+
+                httpConnection.setProxyHost(hostConfiguration.getProxyHost());
+                httpConnection.setProxyPort(hostConfiguration.getProxyPort());
+            }
+            else
+            {
+                finishLastResponse(httpConnection);
+            }
+        }
+
+        // remove the connection from the timeout handler
+        setIdleStartTime(Long.MAX_VALUE);
+
+        return httpConnection;
+    }
+
+    /**
+     * @param hostConfiguration The host configuration.
+     * @param timeout The timeout value.
+     * @return The HttpConnection.
+     * @see HttpConnectionManager#getConnection(HostConfiguration, long)
+     * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long)
+     */
+    public HttpConnection getConnection(
+        HostConfiguration hostConfiguration, long timeout)
+    {
+        return getConnectionWithTimeout(hostConfiguration, timeout);
+    }
+
+    /**
+     * @param conn The HttpConnection.
+     * @see HttpConnectionManager#releaseConnection(org.apache.commons.httpclient.HttpConnection)
+     */
+    public void releaseConnection(HttpConnection conn)
+    {
+        if (conn != getLocalHttpConnection())
+        {
+            throw new IllegalStateException("Unexpected release of an unknown connection.");
+        }
+
+        finishLastResponse(getLocalHttpConnection());
+
+        // track the time the connection was made idle
+        setIdleStartTime(System.currentTimeMillis());
+    }
+
+    /**
+     * @param idleTimeout The timeout value.
+     * @since 3.0
+     */
+    public void closeIdleConnections(long idleTimeout)
+    {
+        long maxIdleTime = System.currentTimeMillis() - idleTimeout;
+        if (getIdleStartTime() <= maxIdleTime)
+        {
+            getLocalHttpConnection().close();
+        }
+    }
+
+    public HttpConnectionManagerParams getParams()
+    {
+        return this.params;
+    }
+
+    public void setParams(HttpConnectionManagerParams params)
+    {
+        if (params == null)
+        {
+            throw new IllegalArgumentException("Parameters may not be null");
+        }
+        this.params = params;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/package.html
new file mode 100644
index 0000000..abed33f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/http/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The HTTP File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileNameParser.java
new file mode 100644
index 0000000..cc60007
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileNameParser.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.https;
+
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+
+/**
+ * Implementation for https. set default port to 443.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class HttpsFileNameParser extends URLFileNameParser
+{
+    private static final HttpsFileNameParser INSTANCE = new HttpsFileNameParser();
+
+    public HttpsFileNameParser()
+    {
+        super(443);
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileProvider.java
new file mode 100644
index 0000000..eab42f9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/HttpsFileProvider.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.https;
+
+import org.apache.commons.vfs.provider.http.HttpFileProvider;
+
+/**
+ * An HTTPS provider that uses commons-httpclient.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpsFileProvider
+    extends HttpFileProvider
+{
+    public HttpsFileProvider()
+    {
+        super();
+        setFileNameParser(HttpsFileNameParser.getInstance());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/package.html
new file mode 100644
index 0000000..9c75492
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/https/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The HTTPS File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileObject.java
new file mode 100644
index 0000000..e8142fc
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileObject.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.zip.ZipFileObject;
+
+import java.io.IOException;
+import java.security.cert.Certificate;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+/**
+ * A file in a Jar file system.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public class JarFileObject extends ZipFileObject
+{
+    private final JarFileSystem fs;
+
+    private Attributes attributes;
+
+    protected JarFileObject(final FileName name,
+                            final ZipEntry entry,
+                            final JarFileSystem fs,
+                            final boolean zipExists) throws FileSystemException
+    {
+        super(name, entry, fs, zipExists);
+        this.fs = fs;
+
+        try
+        {
+            getAttributes(); // early get the attributes as the zip file might be closed
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+    }
+
+    /**
+     * 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.
+     */
+    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 value of an attribute.
+     */
+    protected Map doGetAttributes()
+        throws Exception
+    {
+        final Map attrs = new HashMap();
+
+        // Add the file system's attributes first
+        final JarFileSystem fs = (JarFileSystem) getFileSystem();
+        addAll(fs.getAttributes(), attrs);
+
+        // Add this file's attributes
+        addAll(getAttributes(), attrs);
+
+        return attrs;
+    }
+
+    /**
+     * Adds the source attributes to the destination map.
+     */
+    private void addAll(final Attributes src, final Map dest)
+    {
+        for (Iterator iterator = src.entrySet().iterator(); iterator.hasNext();)
+        {
+            final Map.Entry entry = (Map.Entry) iterator.next();
+            // final String name = entry.getKey().toString().toLowerCase();
+            final String name = entry.getKey().toString();
+            dest.put(name, entry.getValue());
+        }
+    }
+
+    /**
+     * Return the certificates of this JarEntry.
+     */
+    protected Certificate[] doGetCertificates()
+    {
+        if (entry == null)
+        {
+            return null;
+        }
+
+        return ((JarEntry) entry).getCertificates();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileProvider.java
new file mode 100644
index 0000000..2c6fb7f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileProvider.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.LayeredFileName;
+import org.apache.commons.vfs.provider.zip.ZipFileProvider;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A file system provider for Jar files.  Provides read-only file
+ * systems.  This provides access to Jar specific features like Signing and
+ * Manifest Attributes.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public class JarFileProvider
+    extends ZipFileProvider
+{
+    static final Collection capabilities;
+
+    static
+    {
+        Collection combined = new ArrayList();
+        combined.addAll(ZipFileProvider.capabilities);
+        combined.addAll(Arrays.asList(new Capability[]
+            {
+                Capability.ATTRIBUTES,
+                Capability.FS_ATTRIBUTES,
+                Capability.SIGNING,
+                Capability.MANIFEST_ATTRIBUTES,
+                Capability.VIRTUAL
+            }));
+        capabilities = Collections.unmodifiableCollection(combined);
+    }
+
+    public JarFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Creates a layered file system.  This method is called if the file system
+     * is not cached.
+     *
+     * @param scheme The URI scheme.
+     * @param file   The file to create the file system on top of.
+     * @return The file system.
+     */
+    protected FileSystem doCreateFileSystem(final String scheme,
+                                            final FileObject file,
+                                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        final FileName name =
+            new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
+        return new JarFileSystem(name, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileSystem.java
new file mode 100644
index 0000000..bbc8ce4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarFileSystem.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.zip.ZipFileObject;
+import org.apache.commons.vfs.provider.zip.ZipFileSystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.jar.Attributes;
+import java.util.jar.Attributes.Name;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * A read-only file system for Jar files.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public class JarFileSystem
+    extends ZipFileSystem
+{
+    private Attributes attributes;
+
+    protected JarFileSystem(final FileName rootName,
+                            final FileObject file,
+                            final FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        super(rootName, file, fileSystemOptions);
+    }
+
+    protected ZipFile createZipFile(File file) throws FileSystemException
+    {
+        try
+        {
+            return new JarFile(file);
+        }
+        catch (IOException ioe)
+        {
+            throw new FileSystemException("vfs.provider.jar/open-jar-file.error", file, ioe);
+        }
+    }
+
+    protected ZipFileObject createZipFileObject(FileName name,
+                                                ZipEntry entry) throws FileSystemException
+    {
+        return new JarFileObject(name, entry, this, true);
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        // super.addCapabilities(caps);
+        caps.addAll(JarFileProvider.capabilities);
+    }
+
+    Attributes getAttributes() throws IOException
+    {
+        if (attributes == null)
+        {
+            final Manifest man = ((JarFile) getZipFile()).getManifest();
+            if (man == null)
+            {
+                attributes = new Attributes(1);
+            }
+            else
+            {
+                attributes = man.getMainAttributes();
+                if (attributes == null)
+                {
+                    attributes = new Attributes(1);
+                }
+            }
+        }
+
+        return attributes;
+    }
+
+    Object getAttribute(Name attrName)
+        throws FileSystemException
+    {
+        try
+        {
+            final Attributes attr = getAttributes();
+            final String value = attr.getValue(attrName);
+            return value;
+        }
+        catch (IOException ioe)
+        {
+            throw new FileSystemException(attrName.toString(), ioe);
+        }
+    }
+
+    Name lookupName(String attrName)
+    {
+        if (Name.CLASS_PATH.toString().equals(attrName))
+        {
+            return Name.CLASS_PATH;
+        }
+        else if (Name.CONTENT_TYPE.toString().equals(attrName))
+        {
+            return Name.CONTENT_TYPE;
+        }
+        else if (Name.EXTENSION_INSTALLATION.toString().equals(attrName))
+        {
+            return Name.EXTENSION_INSTALLATION;
+        }
+        else if (Name.EXTENSION_LIST.toString().equals(attrName))
+        {
+            return Name.EXTENSION_LIST;
+        }
+        else if (Name.EXTENSION_NAME.toString().equals(attrName))
+        {
+            return Name.EXTENSION_NAME;
+        }
+        else if (Name.IMPLEMENTATION_TITLE.toString().equals(attrName))
+        {
+            return Name.IMPLEMENTATION_TITLE;
+        }
+        else if (Name.IMPLEMENTATION_URL.toString().equals(attrName))
+        {
+            return Name.IMPLEMENTATION_URL;
+        }
+        else if (Name.IMPLEMENTATION_VENDOR.toString().equals(attrName))
+        {
+            return Name.IMPLEMENTATION_VENDOR;
+        }
+        else if (Name.IMPLEMENTATION_VENDOR_ID.toString().equals(attrName))
+        {
+            return Name.IMPLEMENTATION_VENDOR_ID;
+        }
+        else if (Name.IMPLEMENTATION_VERSION.toString().equals(attrName))
+        {
+            return Name.IMPLEMENTATION_VENDOR;
+        }
+        else if (Name.MAIN_CLASS.toString().equals(attrName))
+        {
+            return Name.MAIN_CLASS;
+        }
+        else if (Name.MANIFEST_VERSION.toString().equals(attrName))
+        {
+            return Name.MANIFEST_VERSION;
+        }
+        else if (Name.SEALED.toString().equals(attrName))
+        {
+            return Name.SEALED;
+        }
+        else if (Name.SIGNATURE_VERSION.toString().equals(attrName))
+        {
+            return Name.SIGNATURE_VERSION;
+        }
+        else if (Name.SPECIFICATION_TITLE.toString().equals(attrName))
+        {
+            return Name.SPECIFICATION_TITLE;
+        }
+        else if (Name.SPECIFICATION_VENDOR.toString().equals(attrName))
+        {
+            return Name.SPECIFICATION_VENDOR;
+        }
+        else if (Name.SPECIFICATION_VERSION.toString().equals(attrName))
+        {
+            return Name.SPECIFICATION_VERSION;
+        }
+        else
+        {
+            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.
+     */
+    public Object getAttribute(String attrName) throws FileSystemException
+    {
+        final Name name = lookupName(attrName);
+        return getAttribute(name);
+    }
+
+
+    protected ZipFile getZipFile() throws FileSystemException
+    {
+        return super.getZipFile();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarURLConnectionImpl.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarURLConnectionImpl.java
new file mode 100644
index 0000000..36d169c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/JarURLConnectionImpl.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.JarURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.cert.Certificate;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * A default URL connection that will work for most file systems.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision$ $Date$
+ */
+public class JarURLConnectionImpl
+    extends JarURLConnection
+{
+    // This is because JarURLConnection SUCKS
+    private static final String HACK_URL = "jar:http://somehost/somejar.jar!/";
+
+    private final FileContent content;
+    private final URL parentURL;
+    private final JarFileObject file;
+    private final String entryName;
+
+    public JarURLConnectionImpl(JarFileObject file, FileContent content)
+        throws MalformedURLException, FileSystemException
+    {
+        //This is because JarURLConnection SUCKS!!
+        super(new URL(HACK_URL));
+
+        this.url = file.getURL();
+        this.content = content;
+        this.parentURL = file.getURL();
+        this.entryName = file.getName().getPath();
+        this.file = file;
+    }
+
+
+    public URL getJarFileURL()
+    {
+        return parentURL;
+    }
+
+
+    public String getEntryName()
+    {
+        return entryName;
+    }
+
+
+    public JarFile getJarFile() throws IOException
+    {
+        throw new FileSystemException("vfs.provider.jar/jar-file-no-access.error");
+    }
+
+
+    public Manifest getManifest() throws IOException
+    {
+        return file.getManifest();
+    }
+
+
+    public JarEntry getJarEntry() throws IOException
+    {
+        throw new FileSystemException("vfs.provider.jar/jar-entry-no-access.error");
+    }
+
+
+    public Attributes getAttributes() throws IOException
+    {
+        return file.getAttributes();
+    }
+
+
+    public Certificate[] getCertificates()
+    {
+        return file.doGetCertificates();
+    }
+
+
+    public void connect()
+    {
+        connected = true;
+    }
+
+    public InputStream getInputStream()
+        throws IOException
+    {
+        return content.getInputStream();
+    }
+
+    public OutputStream getOutputStream()
+        throws IOException
+    {
+        return content.getOutputStream();
+    }
+
+    public int getContentLength()
+    {
+        try
+        {
+            return (int) content.getSize();
+        }
+        catch (FileSystemException fse)
+        {
+            // Ignore the error.
+        }
+
+        return -1;
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/package.html
new file mode 100644
index 0000000..a740502
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/jar/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Jar File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/DefaultLocalFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/DefaultLocalFileProvider.java
new file mode 100644
index 0000000..9180e05
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/DefaultLocalFileProvider.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.LocalFileProvider;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.Os;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A file system provider, which uses direct file access.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class DefaultLocalFileProvider
+    extends AbstractOriginatingFileProvider
+    implements LocalFileProvider
+{
+    /** The provider's capabilities. */
+    public static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.CREATE,
+        Capability.DELETE,
+        Capability.RENAME,
+        Capability.GET_TYPE,
+        Capability.GET_LAST_MODIFIED,
+        Capability.SET_LAST_MODIFIED_FILE,
+        Capability.SET_LAST_MODIFIED_FOLDER,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.WRITE_CONTENT,
+        Capability.APPEND_CONTENT,
+        Capability.RANDOM_ACCESS_READ,
+        Capability.RANDOM_ACCESS_WRITE
+    }));
+
+    public DefaultLocalFileProvider()
+    {
+        super();
+
+        if (Os.isFamily(Os.OS_FAMILY_WINDOWS))
+        {
+            setFileNameParser(new WindowsFileNameParser());
+        }
+        else
+        {
+            setFileNameParser(new GenericFileNameParser());
+        }
+    }
+
+    /**
+     * Determines if a name is an absolute file name.
+     * @param name The file name.
+     * @return true if the name is absolute, false otherwise.
+     */
+    public boolean isAbsoluteLocalName(final String name)
+    {
+        return ((LocalFileNameParser) getFileNameParser()).isAbsoluteName(name);
+    }
+
+    /**
+     * Finds a local file, from its local name.
+     * @param name The name of the file to locate.
+     * @return the located FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject findLocalFile(final String name)
+        throws FileSystemException
+    {
+        StringBuffer uri = new StringBuffer(name.length() + 5);
+        uri.append("file:");
+        uri.append(name);
+        FileName filename = parseUri(null, uri.toString());
+        return findFile(filename, null);
+    }
+
+    /**
+     * Finds a local file.
+     * @param file The File to locate.
+     * @return the located FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject findLocalFile(final File file)
+        throws FileSystemException
+    {
+        return findLocalFile(UriParser.encode(file.getAbsolutePath()));
+        // return findLocalFile(file.getAbsolutePath());
+    }
+
+    /**
+     * Creates the filesystem.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Create the file system
+        final LocalFileName rootName = (LocalFileName) name;
+        return new LocalFileSystem(rootName, rootName.getRootFile(), fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/GenericFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/GenericFileNameParser.java
new file mode 100644
index 0000000..697ca0c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/GenericFileNameParser.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * A general-purpose file name parser.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class GenericFileNameParser
+    extends LocalFileNameParser
+{
+    private static final GenericFileNameParser INSTANCE = new GenericFileNameParser();
+
+    /**
+     * retrieve a instance to this parser.
+     *
+     * @return the parser
+     */
+    public static GenericFileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+
+    /**
+     * Pops the root prefix off a URI, which has had the scheme removed.
+     */
+    protected String extractRootPrefix(final String uri,
+                                       final StringBuffer name)
+        throws FileSystemException
+    {
+        // TODO - this class isn't generic at all.  Need to fix this
+
+        // Looking for <sep>
+        if (name.length() == 0 || name.charAt(0) != '/')
+        {
+            throw new FileSystemException("vfs.provider.local/not-absolute-file-name.error", uri);
+        }
+
+        // do not strip the separator, BUT also return it ...
+        return "/";
+    }
+
+    /*
+     * ... this is why whe need this:
+     * here the rootFilename can only be "/" (see above) put this "/" is also in the pathname
+     * so its of no value for the LocalFileName instance
+     */
+    protected FileName createFileName(String scheme, final String rootFile, final String path, final FileType type)
+    {
+        return new LocalFileName(scheme, "", path, type);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFile.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFile.java
new file mode 100644
index 0000000..7ee2883
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFile.java
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.RandomAccessMode;
+import org.apache.commons.vfs.util.FileObjectUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+/**
+ * A file object implementation which uses direct file access.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Revision$ $Date$
+ */
+public class LocalFile
+    extends AbstractFileObject
+    implements FileObject
+{
+    private final String rootFile;
+
+    private File file;
+
+    /**
+     * Creates a non-root file.
+     */
+    protected LocalFile(final LocalFileSystem fileSystem,
+                        final String rootFile,
+                        final FileName name) throws FileSystemException
+    {
+        super(name, fileSystem);
+        this.rootFile = rootFile;
+    }
+
+    /**
+     * Returns the local file that this file object represents.
+     */
+    protected File getLocalFile()
+    {
+        return file;
+    }
+
+    /**
+     * Attaches this file object to its file resource.
+     */
+    protected void doAttach()
+        throws Exception
+    {
+        if (file == null)
+        {
+            // Remove the "file:///"
+            // LocalFileName localFileName = (LocalFileName) getName();
+            String fileName = rootFile + getName().getPathDecoded();
+            // fileName = UriParser.decode(fileName);
+            file = new File(fileName);
+        }
+    }
+
+    /**
+     * Returns the file's type.
+     */
+    protected FileType doGetType()
+        throws Exception
+    {
+        // JDK BUG: 6192331
+        // if (!file.exists())
+        if (!file.exists() && file.length() < 1)
+        {
+            return FileType.IMAGINARY;
+        }
+
+        if (file.isDirectory())
+        {
+            return FileType.FOLDER;
+        }
+
+        // In doubt, treat an existing file as file
+        // if (file.isFile())
+        // {
+            return FileType.FILE;
+        // }
+
+        // throw new FileSystemException("vfs.provider.local/get-type.error", file);
+    }
+
+    /**
+     * Returns the children of the file.
+     */
+    protected String[] doListChildren()
+        throws Exception
+    {
+        return UriParser.encode(file.list());
+    }
+
+    /**
+     * Deletes this file, and all children.
+     */
+    protected void doDelete()
+        throws Exception
+    {
+        if (!file.delete())
+        {
+            throw new FileSystemException("vfs.provider.local/delete-file.error", file);
+        }
+    }
+
+    /**
+     * rename this file
+     */
+    protected void doRename(final FileObject newfile) throws Exception
+    {
+        LocalFile newLocalFile = (LocalFile) FileObjectUtils.getAbstractFileObject(newfile);
+
+        if (!file.renameTo(newLocalFile.getLocalFile()))
+        {
+            throw new FileSystemException("vfs.provider.local/rename-file.error",
+                new String[]{file.toString(), newfile.toString()});
+        }
+    }
+
+    /**
+     * Creates this folder.
+     */
+    protected void doCreateFolder()
+        throws Exception
+    {
+        if (!file.mkdirs())
+        {
+            throw new FileSystemException("vfs.provider.local/create-folder.error", file);
+        }
+    }
+
+    /**
+     * Determines if this file can be written to.
+     */
+    protected boolean doIsWriteable() throws FileSystemException
+    {
+        return file.canWrite();
+    }
+
+    /**
+     * Determines if this file is hidden.
+     */
+    protected boolean doIsHidden()
+    {
+        return file.isHidden();
+    }
+
+    /**
+     * Determines if this file can be read.
+     */
+    protected boolean doIsReadable() throws FileSystemException
+    {
+        return file.canRead();
+    }
+
+    /**
+     * Gets the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime() throws FileSystemException
+    {
+        return file.lastModified();
+    }
+
+    /**
+     * Sets the last modified time of this file.
+     */
+    protected boolean doSetLastModTime(final long modtime)
+        throws FileSystemException
+    {
+        return file.setLastModified(modtime);
+    }
+
+    /**
+     * Creates an input stream to read the content from.
+     */
+    protected InputStream doGetInputStream()
+        throws Exception
+    {
+        return new FileInputStream(file);
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend)
+        throws Exception
+    {
+        return new FileOutputStream(file.getPath(), bAppend);
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize()
+        throws Exception
+    {
+        return file.length();
+    }
+
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        return new LocalFileRandomAccessContent(file, mode);
+    }
+
+    protected boolean doIsSameFile(FileObject destFile) throws FileSystemException
+    {
+        if (!FileObjectUtils.isInstanceOf(destFile, LocalFile.class))
+        {
+            return false;
+        }
+
+        LocalFile destLocalFile = (LocalFile) FileObjectUtils.getAbstractFileObject(destFile);
+        if (!exists() || !destLocalFile.exists())
+        {
+            return false;
+        }
+
+        try
+        {
+            return file.getCanonicalPath().equals(destLocalFile.file.getCanonicalPath());
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileName.java
new file mode 100644
index 0000000..67f6948
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileName.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileName;
+
+/**
+ * A local file URI.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class LocalFileName extends AbstractFileName
+{
+    private final String rootFile;
+
+    protected LocalFileName(final String scheme,
+                            final String rootFile,
+                            final String path,
+                            final FileType type)
+    {
+        super(scheme, path, type);
+        this.rootFile = rootFile;
+    }
+
+    /**
+     * Returns the root file for this file.
+     * @return The root file name.
+     */
+    public String getRootFile()
+    {
+        return rootFile;
+    }
+
+    /**
+     * Factory method for creating name instances.
+     * @param path The file path.
+     * @param type The file type.
+     * @return The FileName.
+     */
+    public FileName createName(final String path, FileType type)
+    {
+        return new LocalFileName(getScheme(), rootFile, path, type);
+    }
+
+    /**
+     * Builds the root URI for this file name.
+     */
+    protected void appendRootUri(final StringBuffer buffer, boolean addPassword)
+    {
+        buffer.append(getScheme());
+        buffer.append("://");
+        buffer.append(rootFile);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java
new file mode 100644
index 0000000..b294ad8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileNameParser.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileNameParser;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+
+/**
+ * A name parser.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class LocalFileNameParser extends AbstractFileNameParser
+{
+    /**
+     * Determines if a name is an absolute file name.
+     * @param name The file name.
+     * @return true if the name is absolute, false otherwise.
+     */
+    public boolean isAbsoluteName(final String name)
+    {
+        // TODO - this is yucky
+        StringBuffer b = new StringBuffer(name);
+        try
+        {
+            UriParser.fixSeparators(b);
+            extractRootPrefix(name, b);
+            return true;
+        }
+        catch (FileSystemException e)
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Pops the root prefix off a URI, which has had the scheme removed.
+     */
+    protected abstract String extractRootPrefix(final String uri,
+                                                final StringBuffer name)
+        throws FileSystemException;
+
+
+    public FileName parseUri(final VfsComponentContext context, FileName base, final String filename)
+        throws FileSystemException
+    {
+        final StringBuffer name = new StringBuffer();
+
+        // Extract the scheme
+        String scheme = UriParser.extractScheme(filename, name);
+        if (scheme == null)
+        {
+            scheme = "file";
+        }
+
+        // Remove encoding, and adjust the separators
+        UriParser.canonicalizePath(name, 0, name.length(), this);
+
+        UriParser.fixSeparators(name);
+
+        // Extract the root prefix
+        final String rootFile = extractRootPrefix(filename, name);
+
+        // Normalise the path
+        FileType fileType = UriParser.normalisePath(name);
+
+        final String path = name.toString();
+
+        return createFileName(
+            scheme,
+            rootFile,
+            path,
+            fileType);
+    }
+
+    protected abstract FileName createFileName(String scheme, final String rootFile, final String path,
+                                               final FileType type);
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileRandomAccessContent.java
new file mode 100644
index 0000000..199da0b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileRandomAccessContent.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractRandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+
+/**
+ * RandomAccess for local files
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+class LocalFileRandomAccessContent extends AbstractRandomAccessContent
+{
+    // private final LocalFile localFile;
+    private final RandomAccessFile raf;
+    private final InputStream rafis;
+
+    LocalFileRandomAccessContent(final File localFile, final RandomAccessMode mode) throws FileSystemException
+    {
+        super(mode);
+
+        try
+        {
+            raf = new RandomAccessFile(localFile, mode.getModeString());
+            rafis = new InputStream()
+            {
+                public int read() throws IOException
+                {
+                    try
+                    {
+                        return raf.readByte();
+                    }
+                    catch (EOFException e)
+                    {
+                        return -1;
+                    }
+                }
+
+                public long skip(long n) throws IOException
+                {
+                    raf.seek(raf.getFilePointer() + n);
+                    return n;
+                }
+
+                public void close() throws IOException
+                {
+                    raf.close();
+                }
+
+                public int read(byte[] b) throws IOException
+                {
+                    return raf.read(b);
+                }
+
+                public int read(byte[] b, int off, int len) throws IOException
+                {
+                    return raf.read(b, off, len);
+                }
+
+                public int available() throws IOException
+                {
+                    long available = raf.length() - raf.getFilePointer();
+                    if (available > Integer.MAX_VALUE)
+                    {
+                        return Integer.MAX_VALUE;
+                    }
+
+                    return (int) available;
+                }
+            };
+        }
+        catch (FileNotFoundException e)
+        {
+            throw new FileSystemException("vfs.provider/random-access-open-failed.error", localFile);
+        }
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return raf.getFilePointer();
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        raf.seek(pos);
+    }
+
+    public long length() throws IOException
+    {
+        return raf.length();
+    }
+
+    public void close() throws IOException
+    {
+        raf.close();
+    }
+
+    public byte readByte() throws IOException
+    {
+        return raf.readByte();
+    }
+
+    public char readChar() throws IOException
+    {
+        return raf.readChar();
+    }
+
+    public double readDouble() throws IOException
+    {
+        return raf.readDouble();
+    }
+
+    public float readFloat() throws IOException
+    {
+        return raf.readFloat();
+    }
+
+    public int readInt() throws IOException
+    {
+        return raf.readInt();
+    }
+
+    public int readUnsignedByte() throws IOException
+    {
+        return raf.readUnsignedByte();
+    }
+
+    public int readUnsignedShort() throws IOException
+    {
+        return raf.readUnsignedShort();
+    }
+
+    public long readLong() throws IOException
+    {
+        return raf.readLong();
+    }
+
+    public short readShort() throws IOException
+    {
+        return raf.readShort();
+    }
+
+    public boolean readBoolean() throws IOException
+    {
+        return raf.readBoolean();
+    }
+
+    public int skipBytes(int n) throws IOException
+    {
+        return raf.skipBytes(n);
+    }
+
+    public void readFully(byte[] b) throws IOException
+    {
+        raf.readFully(b);
+    }
+
+    public void readFully(byte[] b, int off, int len) throws IOException
+    {
+        raf.readFully(b, off, len);
+    }
+
+    public String readUTF() throws IOException
+    {
+        return raf.readUTF();
+    }
+
+    public void writeDouble(double v) throws IOException
+    {
+        raf.writeDouble(v);
+    }
+
+    public void writeFloat(float v) throws IOException
+    {
+        raf.writeFloat(v);
+    }
+
+    public void write(int b) throws IOException
+    {
+        raf.write(b);
+    }
+
+    public void writeByte(int v) throws IOException
+    {
+        raf.writeByte(v);
+    }
+
+    public void writeChar(int v) throws IOException
+    {
+        raf.writeChar(v);
+    }
+
+    public void writeInt(int v) throws IOException
+    {
+        raf.writeInt(v);
+    }
+
+    public void writeShort(int v) throws IOException
+    {
+        raf.writeShort(v);
+    }
+
+    public void writeLong(long v) throws IOException
+    {
+        raf.writeLong(v);
+    }
+
+    public void writeBoolean(boolean v) throws IOException
+    {
+        raf.writeBoolean(v);
+    }
+
+    public void write(byte[] b) throws IOException
+    {
+        raf.write(b);
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        raf.write(b, off, len);
+    }
+
+    public void writeBytes(String s) throws IOException
+    {
+        raf.writeBytes(s);
+    }
+
+    public void writeChars(String s) throws IOException
+    {
+        raf.writeChars(s);
+    }
+
+    public void writeUTF(String str) throws IOException
+    {
+        raf.writeUTF(str);
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return rafis;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileSystem.java
new file mode 100644
index 0000000..f9bcab0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/LocalFileSystem.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.util.Collection;
+
+/**
+ * A local file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class LocalFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    private final String rootFile;
+
+    public LocalFileSystem(final FileName rootName,
+                           final String rootFile,
+                           final FileSystemOptions opts)
+    {
+        super(rootName, null, opts);
+        this.rootFile = rootFile;
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name) throws FileSystemException
+    {
+        // Create the file
+        return new LocalFile(this, rootFile, name);
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(DefaultLocalFileProvider.capabilities);
+    }
+
+    /**
+     * Creates a temporary local copy of a file and its descendents.
+     */
+    protected File doReplicateFile(final FileObject fileObject,
+                                   final FileSelector selector)
+        throws Exception
+    {
+        final LocalFile localFile = (LocalFile) fileObject;
+        final File file = localFile.getLocalFile();
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null)
+        {
+            final FilePermission requiredPerm = new FilePermission(file.getAbsolutePath(), "read");
+            sm.checkPermission(requiredPerm);
+        }
+        return file;
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileName.java
new file mode 100644
index 0000000..d6368c8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileName.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * A local file URI.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class WindowsFileName extends LocalFileName
+{
+    protected WindowsFileName(final String scheme,
+                              final String rootFile,
+                              final String path,
+                              final FileType type)
+    {
+        super(scheme, rootFile, path, type);
+    }
+
+    /**
+     * Factory method for creating name instances.
+     * @param path The file path.
+     * @param type The file type.
+     * @return The FileName.
+     */
+    public FileName createName(final String path, FileType type)
+    {
+        return new WindowsFileName(getScheme(), getRootFile(), path, type);
+    }
+
+    /**
+     * Builds the root URI for this file name.
+     */
+    protected void appendRootUri(final StringBuffer buffer, boolean addPassword)
+    {
+        buffer.append(getScheme());
+        buffer.append("://");
+        if (getRootFile() != null && !getRootFile().startsWith("/"))
+        {
+            // next is drive-letter (else unc name)
+            buffer.append("/");
+        }
+        buffer.append(getRootFile());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileNameParser.java
new file mode 100644
index 0000000..ca2099f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/WindowsFileNameParser.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * A parser for Windows file names.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class WindowsFileNameParser
+    extends LocalFileNameParser
+{
+    /**
+     * Pops the root prefix off a URI, which has had the scheme removed.
+     */
+    protected String extractRootPrefix(final String uri,
+                                       final StringBuffer name)
+        throws FileSystemException
+    {
+        return extractWindowsRootPrefix(uri, name);
+    }
+
+    protected FileName createFileName(String scheme, final String rootFile, final String path, final FileType type)
+    {
+        return new WindowsFileName(scheme, rootFile, path, type);
+    }
+
+    /**
+     * Extracts a Windows root prefix from a name.
+     */
+    private String extractWindowsRootPrefix(final String uri,
+                                            final StringBuffer name)
+        throws FileSystemException
+    {
+        // Looking for:
+        // ('/'){0, 3} <letter> ':' '/'
+        // ['/'] '//' <name> '/' <name> ( '/' | <end> )
+
+        // Skip over first 4 (unc) leading '/' chars
+        int startPos = 0;
+        int maxlen = Math.min(4, name.length());
+        for (; startPos < maxlen && name.charAt(startPos) == '/'; startPos++)
+        {
+        }
+        if (startPos == maxlen && name.length() > startPos && name.charAt(startPos + 1) == '/')
+        {
+            // Too many '/'
+            throw new FileSystemException("vfs.provider.local/not-absolute-file-name.error", uri);
+        }
+        name.delete(0, startPos);
+
+        // Look for drive name
+        String driveName = extractDrivePrefix(name);
+        if (driveName != null)
+        {
+            return driveName;
+        }
+
+        // Look for UNC name
+        if (startPos < 2)
+        {
+            throw new FileSystemException("vfs.provider.local/not-absolute-file-name.error", uri);
+        }
+
+        return "//" + extractUNCPrefix(uri, name);
+    }
+
+    /**
+     * Extracts a drive prefix from a path.  Leading '/' chars have been removed.
+     */
+    private String extractDrivePrefix(final StringBuffer name)
+    {
+        // Looking for <letter> ':' '/'
+        if (name.length() < 3)
+        {
+            // Too short
+            return null;
+        }
+        char ch = name.charAt(0);
+        if (ch == '/' || ch == ':')
+        {
+            // Missing drive letter
+            return null;
+        }
+        if (name.charAt(1) != ':')
+        {
+            // Missing ':'
+            return null;
+        }
+        if (name.charAt(2) != '/')
+        {
+            // Missing separator
+            return null;
+        }
+
+        String prefix = name.substring(0, 2);
+        name.delete(0, 2);
+
+        return prefix.intern();
+    }
+
+    /**
+     * Extracts a UNC name from a path.  Leading '/' chars have been removed.
+     */
+    private String extractUNCPrefix(final String uri,
+                                    final StringBuffer name)
+        throws FileSystemException
+    {
+        // Looking for <name> '/' <name> ( '/' | <end> )
+
+        // Look for first separator
+        int maxpos = name.length();
+        int pos = 0;
+        for (; pos < maxpos && name.charAt(pos) != '/'; pos++)
+        {
+        }
+        pos++;
+        if (pos >= maxpos)
+        {
+            throw new FileSystemException("vfs.provider.local/missing-share-name.error", uri);
+        }
+
+        // Now have <name> '/'
+        int startShareName = pos;
+        for (; pos < maxpos && name.charAt(pos) != '/'; pos++)
+        {
+        }
+        if (pos == startShareName)
+        {
+            throw new FileSystemException("vfs.provider.local/missing-share-name.error", uri);
+        }
+
+        // Now have <name> '/' <name> ( '/' | <end> )
+        String prefix = name.substring(0, pos);
+        name.delete(0, pos);
+        return prefix;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/package.html
new file mode 100644
index 0000000..c826d13
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/local/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Local File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/package.html
new file mode 100644
index 0000000..a661b05
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The File Provider API, and utility classes.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileData.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileData.java
new file mode 100644
index 0000000..0ea42b0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileData.java
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+/**
+ * RAM File Object Data.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class RamFileData implements Serializable
+{
+    /**
+     * File Name.
+     */
+    private FileName name;
+
+    /**
+     * File Type.
+     */
+    private FileType type;
+
+    /**
+     * Bytes.
+     */
+    private byte[] buffer;
+
+    /**
+     * Last modified time
+     */
+    private long lastModified;
+
+    /**
+     * Children
+     */
+    private final Collection children;
+
+    /**
+     * Constructor.
+     * @param name The file name.
+     */
+    public RamFileData(FileName name)
+    {
+        super();
+        this.children = Collections.synchronizedCollection(new ArrayList());
+        this.clear();
+        if (name == null)
+        {
+            throw new IllegalArgumentException("name can not be null");
+        }
+        this.name = name;
+    }
+
+    /**
+     * @return Returns the buffer.
+     */
+    byte[] getBuffer()
+    {
+        return buffer;
+    }
+
+    /**
+     * @param buffer The buffer.
+     */
+    void setBuffer(byte[] buffer)
+    {
+        updateLastModified();
+        this.buffer = buffer;
+    }
+
+    /**
+     * @return Returns the lastModified.
+     */
+    long getLastModified()
+    {
+        return lastModified;
+    }
+
+    /**
+     * @param lastModified
+     *            The lastModified to set.
+     */
+    void setLastModified(long lastModified)
+    {
+        this.lastModified = lastModified;
+    }
+
+    /**
+     * @return Returns the type.
+     */
+    FileType getType()
+    {
+        return type;
+    }
+
+    /**
+     * @param type
+     *            The type to set.
+     */
+    void setType(FileType type)
+    {
+        this.type = type;
+    }
+
+    /**
+     *
+     */
+    void clear()
+    {
+        this.buffer = new byte[0];
+        updateLastModified();
+        this.type = FileType.IMAGINARY;
+        this.children.clear();
+        this.name = null;
+    }
+
+    void updateLastModified()
+    {
+        this.lastModified = System.currentTimeMillis();
+    }
+
+    /**
+     * @return Returns the name.
+     */
+    FileName getName()
+    {
+        return name;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    public String toString()
+    {
+        return this.name.toString();
+    }
+
+    /**
+     * Add a child.
+     *
+     * @param data The file data.
+     * @throws FileSystemException if an error occurs.
+     */
+    void addChild(RamFileData data) throws FileSystemException
+    {
+        if (!this.getType().hasChildren())
+        {
+            throw new FileSystemException(
+                    "A child can only be added in a folder");
+        }
+
+        if (data == null)
+        {
+            throw new FileSystemException("No child can be null");
+        }
+
+        if (this.children.contains(data))
+        {
+            throw new FileSystemException("Child already exists. " + data);
+        }
+
+        this.children.add(data);
+        updateLastModified();
+    }
+
+    /**
+     * Remove a child.
+     *
+     * @param data The file data.
+     * @throws FileSystemException if an error occurs.
+     */
+    void removeChild(RamFileData data) throws FileSystemException
+    {
+        if (!this.getType().hasChildren())
+        {
+            throw new FileSystemException(
+                    "A child can only be removed from a folder");
+        }
+        if (!this.children.contains(data))
+        {
+            throw new FileSystemException("Child not found. " + data);
+        }
+        this.children.remove(data);
+        updateLastModified();
+    }
+
+    /**
+     * @return Returns the children.
+     */
+    Collection getChildren()
+    {
+        if (name == null)
+        {
+            throw new IllegalStateException("Data is clear");
+        }
+        return children;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals(Object o)
+    {
+        if (this == o)
+        {
+            return true;
+        }
+        if (!(o instanceof RamFileData))
+        {
+            return false;
+        }
+        RamFileData data = (RamFileData) o;
+        return this.getName().equals(data.getName());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return this.getName().hashCode();
+    }
+
+    boolean hasChildren(RamFileData data)
+    {
+        return this.children.contains(data);
+    }
+
+    /**
+     * @return Returns the size of the buffer
+     */
+    int size()
+    {
+        return buffer.length;
+    }
+
+    /**
+     * Resize the buffer
+     *
+     * @param newSize The new buffer size.
+     */
+    void resize(int newSize)
+    {
+        int size = this.size();
+        byte[] newBuf = new byte[newSize];
+        System.arraycopy(this.buffer, 0, newBuf, 0, size);
+        this.buffer = newBuf;
+        updateLastModified();
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileObject.java
new file mode 100644
index 0000000..b1d749a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileObject.java
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * A RAM File contains a single RAM FileData instance, it provides methods to
+ * access the data by implementing FileObject interface.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class RamFileObject extends AbstractFileObject implements FileObject
+{
+    /**
+     * File System.
+     */
+    private final RamFileSystem fs;
+
+    /**
+     * RAM File Object Data.
+     */
+    private RamFileData data;
+
+    /**
+     * @param name The name of the file.
+     * @param fs The FileSystem.
+     */
+    protected RamFileObject(FileName name, RamFileSystem fs)
+    {
+        super(name, fs);
+        this.fs = fs;
+        this.fs.attach(this);
+    }
+
+    private void save() throws FileSystemException
+    {
+        this.fs.save(this);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetType()
+     */
+    protected FileType doGetType() throws Exception
+    {
+        return data.getType();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doListChildren()
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        return this.fs.listChildren(this.getName());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetContentSize()
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        return this.data.getBuffer().length;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetInputStream()
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        // VFS-210: ram allows to gather an input stream even from a directory. So we need to check the type anyway.
+        if (!getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/read-not-file.error", getName());
+        }
+
+        return new ByteArrayInputStream(this.data.getBuffer());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetOutputStream(boolean)
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        if (!bAppend)
+        {
+            this.data.setBuffer(new byte[0]);
+        }
+        return new RamFileOutputStream(this);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doDelete()
+     */
+    protected void doDelete() throws Exception
+    {
+        fs.delete(this);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetLastModifiedTime()
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        return data.getLastModified();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doSetLastModifiedTime(long)
+     */
+    protected boolean doSetLastModTime(long modtime) throws Exception
+    {
+        data.setLastModified(modtime);
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doCreateFolder()
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        this.injectType(FileType.FOLDER);
+        this.save();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doRename(org.apache.commons.vfs.FileObject)
+     */
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        fs.rename(this, (RamFileObject) newfile);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doGetRandomAccessContent(
+     *      org.apache.commons.vfs.util.RandomAccessMode)
+     */
+    protected RandomAccessContent doGetRandomAccessContent(RandomAccessMode mode)
+            throws Exception
+    {
+        return new RamFileRandomAccessContent(this, mode);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#doAttach()
+     */
+    protected void doAttach() throws Exception
+    {
+        this.fs.attach(this);
+    }
+
+    /**
+     * @return Returns the data.
+     */
+    RamFileData getData()
+    {
+        return data;
+    }
+
+    /**
+     * @param data
+     *            The data to set.
+     */
+    void setData(RamFileData data)
+    {
+        this.data = data;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#injectType(org.apache.commons.vfs.FileType)
+     */
+    protected void injectType(FileType fileType)
+    {
+        this.data.setType(fileType);
+        super.injectType(fileType);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileObject#endOutput()
+     */
+    protected void endOutput() throws Exception
+    {
+        super.endOutput();
+        this.save();
+    }
+
+    /**
+     * @return Returns the size of the RAMFileData
+     */
+    int size()
+    {
+        if (data == null)
+        {
+            return 0;
+        }
+        return data.size();
+    }
+
+    /**
+     * @param newSize
+     * @throws IOException
+     *             if the new size exceeds the limit
+     */
+    synchronized void resize(int newSize) throws IOException
+    {
+        if (fs.getFileSystemOptions() != null)
+        {
+            int maxSize = RamFileSystemConfigBuilder.getInstance().getMaxSize(
+                    fs.getFileSystemOptions());
+            if (fs.size() + newSize - this.size() > maxSize)
+            {
+                throw new IOException("FileSystem capacity (" + maxSize
+                        + ") exceeded.");
+            }
+        }
+        this.data.resize(newSize);
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileOutputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileOutputStream.java
new file mode 100644
index 0000000..fc8bb7e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileOutputStream.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.vfs.FileSystemException;
+
+/**
+ * OutputStream to a RamFile.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class RamFileOutputStream extends OutputStream
+{
+
+    /**
+     * File.
+     */
+    protected RamFileObject file;
+
+    /**
+     * buffer.
+     */
+    protected byte[] buffer1 = new byte[1];
+
+    /** File is open or closed */
+    protected boolean closed = false;
+
+    private IOException exc;
+
+    /**
+     * @param file The base file.
+     */
+    public RamFileOutputStream(RamFileObject file)
+    {
+        super();
+        this.file = file;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#write(byte[], int, int)
+     */
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        int size = this.file.getData().size();
+        int newSize = this.file.getData().size() + len;
+        // Store the Exception in order to notify the client again on close()
+        try
+        {
+            this.file.resize(newSize);
+        }
+        catch (IOException e)
+        {
+            this.exc = e;
+            throw e;
+        }
+        System.arraycopy(b, off, this.file.getData().getBuffer(), size, len);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#write(int)
+     */
+    public void write(int b) throws IOException
+    {
+        buffer1[0] = (byte) b;
+        this.write(buffer1);
+    }
+
+    public void flush() throws IOException
+    {
+    }
+
+    public void close() throws IOException
+    {
+        if (closed)
+        {
+            return;
+        }
+        // Notify on close that there was an IOException while writing
+        if (exc != null)
+        {
+            throw exc;
+        }
+        try
+        {
+            this.closed = true;
+            // Close the
+            this.file.endOutput();
+        }
+        catch (Exception e)
+        {
+            throw new FileSystemException(e);
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileProvider.java
new file mode 100644
index 0000000..610626b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileProvider.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+
+/**
+ * RAM File Provider.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ *
+ */
+public class RamFileProvider extends AbstractOriginatingFileProvider implements
+        FileProvider
+{
+    /** The provider's capabilities. */
+    public static final Collection capabilities = Collections
+            .unmodifiableCollection(Arrays.asList(new Capability[]
+            {Capability.CREATE, Capability.DELETE, Capability.RENAME,
+                    Capability.GET_TYPE, Capability.GET_LAST_MODIFIED,
+                    Capability.SET_LAST_MODIFIED_FILE,
+                    Capability.SET_LAST_MODIFIED_FOLDER,
+                    Capability.LIST_CHILDREN, Capability.READ_CONTENT,
+                    Capability.URI, Capability.WRITE_CONTENT,
+                    Capability.APPEND_CONTENT, Capability.RANDOM_ACCESS_READ,
+                    Capability.RANDOM_ACCESS_WRITE
+            }));
+
+    /**
+     * Constructor.
+     */
+    public RamFileProvider()
+    {
+        super();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractOriginatingFileProvider#doCreateFileSystem(
+     *      org.apache.commons.vfs.FileName, org.apache.commons.vfs.FileSystemOptions)
+     */
+    protected FileSystem doCreateFileSystem(FileName name,
+            FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        return new RamFileSystem(name, fileSystemOptions);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.FileProvider#getCapabilities()
+     */
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileRandomAccessContent.java
new file mode 100644
index 0000000..254a6b2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileRandomAccessContent.java
@@ -0,0 +1,614 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * RAM File Random Access Content.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class RamFileRandomAccessContent implements RandomAccessContent
+{
+    /**
+     * File Pointer
+     */
+    protected int filePointer = 0;
+
+    /**
+     * Buffer
+     */
+    private byte[] buf;
+
+    /**
+     * buffer
+     */
+    private final byte[] buffer8 = new byte[8];
+
+    /**
+     * buffer
+     */
+    private final byte[] buffer4 = new byte[4];
+
+    /**
+     * buffer
+     */
+    private final byte[] buffer2 = new byte[2];
+
+    /**
+     * buffer
+     */
+    private final byte[] buffer1 = new byte[1];
+
+    /**
+     * Mode
+     */
+    private final RandomAccessMode mode;
+
+    /**
+     * File
+     */
+    private final RamFileObject file;
+
+    private final InputStream rafis;
+
+    /**
+     * @param file The file to access.
+     * @param mode The access mode.
+     */
+    public RamFileRandomAccessContent(RamFileObject file, RandomAccessMode mode)
+    {
+        super();
+        this.buf = file.getData().getBuffer();
+        this.file = file;
+        this.mode = mode;
+
+        rafis = new InputStream()
+        {
+            public int read() throws IOException
+            {
+                try
+                {
+                    return readByte();
+                }
+                catch (EOFException e)
+                {
+                    return -1;
+                }
+            }
+
+            public long skip(long n) throws IOException
+            {
+                seek(getFilePointer() + n);
+                return n;
+            }
+
+            public void close() throws IOException
+            {
+            }
+
+            public int read(byte[] b) throws IOException
+            {
+                return read(b, 0, b.length);
+            }
+
+            public int read(byte[] b, int off, int len) throws IOException
+            {
+                int retLen = Math.min(len, getLeftBytes());
+                RamFileRandomAccessContent.this.readFully(b, off, retLen);
+                return retLen;
+            }
+
+            public int available() throws IOException
+            {
+                return getLeftBytes();
+            }
+        };
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.RandomAccessContent#getFilePointer()
+     */
+    public long getFilePointer() throws IOException
+    {
+        return this.filePointer;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.RandomAccessContent#seek(long)
+     */
+    public void seek(long pos) throws IOException
+    {
+        this.filePointer = (int) pos;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.RandomAccessContent#length()
+     */
+    public long length() throws IOException
+    {
+        return buf.length;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.RandomAccessContent#close()
+     */
+    public void close() throws IOException
+    {
+
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readByte()
+     */
+    public byte readByte() throws IOException
+    {
+        return (byte) this.readUnsignedByte();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readChar()
+     */
+    public char readChar() throws IOException
+    {
+        int ch1 = this.readUnsignedByte();
+        int ch2 = this.readUnsignedByte();
+        return (char) ((ch1 << 8) + (ch2 << 0));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readDouble()
+     */
+    public double readDouble() throws IOException
+    {
+        return Double.longBitsToDouble(this.readLong());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readFloat()
+     */
+    public float readFloat() throws IOException
+    {
+        return Float.intBitsToFloat(this.readInt());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readInt()
+     */
+    public int readInt() throws IOException
+    {
+        return (readUnsignedByte() << 24) | (readUnsignedByte() << 16)
+                | (readUnsignedByte() << 8) | readUnsignedByte();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readUnsignedByte()
+     */
+    public int readUnsignedByte() throws IOException
+    {
+        if (filePointer < buf.length)
+        {
+            return buf[filePointer++] & 0xFF;
+        }
+        else
+        {
+            throw new EOFException();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readUnsignedShort()
+     */
+    public int readUnsignedShort() throws IOException
+    {
+        this.readFully(buffer2);
+        return toUnsignedShort(buffer2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readLong()
+     */
+    public long readLong() throws IOException
+    {
+        this.readFully(buffer8);
+        return toLong(buffer8);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readShort()
+     */
+    public short readShort() throws IOException
+    {
+        this.readFully(buffer2);
+        return toShort(buffer2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readBoolean()
+     */
+    public boolean readBoolean() throws IOException
+    {
+        return (this.readUnsignedByte() != 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#skipBytes(int)
+     */
+    public int skipBytes(int n) throws IOException
+    {
+        if (n < 0)
+        {
+            throw new IndexOutOfBoundsException(
+                    "The skip number can't be negative");
+        }
+
+        long newPos = filePointer + n;
+
+        if (newPos > buf.length)
+        {
+            throw new IndexOutOfBoundsException("Tyring to skip too much bytes");
+        }
+
+        seek(newPos);
+
+        return n;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readFully(byte[])
+     */
+    public void readFully(byte[] b) throws IOException
+    {
+        this.readFully(b, 0, b.length);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readFully(byte[], int, int)
+     */
+    public void readFully(byte[] b, int off, int len) throws IOException
+    {
+        if (len < 0)
+        {
+            throw new IndexOutOfBoundsException("Length is lower than 0");
+        }
+
+        if (len > this.getLeftBytes())
+        {
+            throw new IndexOutOfBoundsException("Read length (" + len
+                    + ") is higher than buffer left bytes ("
+                    + this.getLeftBytes() + ") ");
+        }
+
+        System.arraycopy(buf, filePointer, b, off, len);
+
+        filePointer += len;
+    }
+
+    private int getLeftBytes()
+    {
+        return buf.length - filePointer;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readUTF()
+     */
+    public String readUTF() throws IOException
+    {
+        return DataInputStream.readUTF(this);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#write(byte[], int, int)
+     */
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        if (this.getLeftBytes() < len)
+        {
+            int newSize = this.buf.length + len - this.getLeftBytes();
+            this.file.resize(newSize);
+            this.buf = this.file.getData().getBuffer();
+        }
+        System.arraycopy(b, off, this.buf, filePointer, len);
+        this.filePointer += len;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#write(byte[])
+     */
+    public void write(byte[] b) throws IOException
+    {
+        this.write(b, 0, b.length);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeByte(int)
+     */
+    public void writeByte(int i) throws IOException
+    {
+        this.write(i);
+    }
+
+    /**
+     * Build a long from first 8 bytes of the array.
+     *
+     * @author Apache-Commons-Id Team
+     * @param b
+     *            The byte[] to convert.
+     * @return A long.
+     */
+    public static long toLong(byte[] b)
+    {
+        return ((((long) b[7]) & 0xFF) + ((((long) b[6]) & 0xFF) << 8)
+                + ((((long) b[5]) & 0xFF) << 16)
+                + ((((long) b[4]) & 0xFF) << 24)
+                + ((((long) b[3]) & 0xFF) << 32)
+                + ((((long) b[2]) & 0xFF) << 40)
+                + ((((long) b[1]) & 0xFF) << 48) + ((((long) b[0]) & 0xFF) << 56));
+    }
+
+    /**
+     * Build a 8-byte array from a long. No check is performed on the array
+     * length.
+     *
+     * @author Commons-Id Team
+     *
+     * @param n
+     *            The number to convert.
+     * @param b
+     *            The array to fill.
+     * @return A byte[].
+     */
+    public static byte[] toBytes(long n, byte[] b)
+    {
+        b[7] = (byte) (n);
+        n >>>= 8;
+        b[6] = (byte) (n);
+        n >>>= 8;
+        b[5] = (byte) (n);
+        n >>>= 8;
+        b[4] = (byte) (n);
+        n >>>= 8;
+        b[3] = (byte) (n);
+        n >>>= 8;
+        b[2] = (byte) (n);
+        n >>>= 8;
+        b[1] = (byte) (n);
+        n >>>= 8;
+        b[0] = (byte) (n);
+        return b;
+    }
+
+    /**
+     * Build a short from first 2 bytes of the array.
+     *
+     * @author Apache-Commons-Id Team
+     * @param b
+     *            The byte[] to convert.
+     * @return A short.
+     */
+    public static short toShort(byte[] b)
+    {
+        return (short) toUnsignedShort(b);
+    }
+
+    /**
+     * Build a short from first 2 bytes of the array.
+     *
+     * @author Apache-Commons-Id Team
+     * @param b
+     *            The byte[] to convert.
+     * @return A short.
+     */
+    public static int toUnsignedShort(byte[] b)
+    {
+        return ((b[1] & 0xFF) + ((b[0] & 0xFF) << 8));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#write(int)
+     */
+    public void write(int b) throws IOException
+    {
+        buffer1[0] = (byte) b;
+        this.write(buffer1);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeBoolean(boolean)
+     */
+    public void writeBoolean(boolean v) throws IOException
+    {
+        this.write(v ? 1 : 0);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeBytes(java.lang.String)
+     */
+    public void writeBytes(String s) throws IOException
+    {
+        write(s.getBytes());
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeChar(int)
+     */
+    public void writeChar(int v) throws IOException
+    {
+        buffer2[0] = (byte) ((v >>> 8) & 0xFF);
+        buffer2[1] = (byte) ((v >>> 0) & 0xFF);
+        write(buffer2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeChars(java.lang.String)
+     */
+    public void writeChars(String s) throws IOException
+    {
+        int len = s.length();
+        for (int i = 0; i < len; i++)
+        {
+            writeChar(s.charAt(i));
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeDouble(double)
+     */
+    public void writeDouble(double v) throws IOException
+    {
+        writeLong(Double.doubleToLongBits(v));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeFloat(float)
+     */
+    public void writeFloat(float v) throws IOException
+    {
+        writeInt(Float.floatToIntBits(v));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeInt(int)
+     */
+    public void writeInt(int v) throws IOException
+    {
+        buffer4[0] = (byte) ((v >>> 24) & 0xFF);
+        buffer4[1] = (byte) ((v >>> 16) & 0xFF);
+        buffer4[2] = (byte) ((v >>> 8) & 0xFF);
+        buffer4[3] = (byte) (v & 0xFF);
+        write(buffer4);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeLong(long)
+     */
+    public void writeLong(long v) throws IOException
+    {
+        write(toBytes(v, buffer8));
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeShort(int)
+     */
+    public void writeShort(int v) throws IOException
+    {
+        buffer2[0] = (byte) ((v >>> 8) & 0xFF);
+        buffer2[1] = (byte) (v & 0xFF);
+        write(buffer2);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataOutput#writeUTF(java.lang.String)
+     */
+    public void writeUTF(String str) throws IOException
+    {
+        ByteArrayOutputStream out = new ByteArrayOutputStream(str.length());
+        DataOutputStream dataOut = new DataOutputStream(out);
+        dataOut.writeUTF(str);
+        dataOut.flush();
+        dataOut.close();
+        byte[] b = out.toByteArray();
+        write(b);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.io.DataInput#readLine()
+     */
+    public String readLine() throws IOException
+    {
+        throw new UnsupportedOperationException("deprecated");
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return rafis;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystem.java
new file mode 100644
index 0000000..de6a88b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystem.java
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+/**
+ * A RAM File System.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class RamFileSystem extends AbstractFileSystem implements Serializable
+{
+    /**
+     * Cache of RAM File Data
+     */
+    private final Map cache;
+
+    /**
+     * @param rootName The root file name.
+     * @param fileSystemOptions The FileSystem options.
+     */
+    protected RamFileSystem(FileName rootName,
+            FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+        this.cache = Collections.synchronizedMap(new HashMap());
+        // create root
+        RamFileData rootData = new RamFileData(rootName);
+        rootData.setType(FileType.FOLDER);
+        rootData.setLastModified(System.currentTimeMillis());
+        this.cache.put(rootName, rootData);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileSystem#createFile(org.apache.commons.vfs.FileName)
+     */
+    protected FileObject createFile(FileName name) throws Exception
+    {
+        RamFileObject file = new RamFileObject(name, this);
+        return file;
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.commons.vfs.provider.AbstractFileSystem#addCapabilities(java.util.Collection)
+     */
+    protected void addCapabilities(Collection caps)
+    {
+        caps.addAll(RamFileProvider.capabilities);
+    }
+
+    /**
+     * @param name The name of the file.
+     * @return children The names of the children.
+     */
+    String[] listChildren(FileName name)
+    {
+        RamFileData data = (RamFileData) this.cache.get(name);
+        if (data == null || !data.getType().hasChildren())
+        {
+            return null;
+        }
+        Collection children = data.getChildren();
+        String[] names;
+
+        synchronized(children) {
+            names = new String[children.size()];
+
+            int pos = 0;
+            Iterator iter = children.iterator();
+            while (iter.hasNext())
+            {
+                RamFileData childData = (RamFileData) iter.next();
+                names[pos] = childData.getName().getBaseName();
+                pos++;
+            }
+        }
+
+        return names;
+    }
+
+    /**
+     * Delete a file
+     *
+     * @param file
+     * @throws FileSystemException
+     */
+    void delete(RamFileObject file) throws FileSystemException
+    {
+        // root is read only check
+        if (file.getParent() == null)
+        {
+            throw new FileSystemException("unable to delete root");
+        }
+
+        // Remove reference from cache
+        this.cache.remove(file.getName());
+        // Notify the parent
+        RamFileObject parent = (RamFileObject) this.resolveFile(file
+                .getParent().getName());
+        parent.getData().removeChild(file.getData());
+        parent.close();
+        // Close the file
+        file.getData().clear();
+        file.close();
+    }
+
+    /**
+     * Saves a file
+     *
+     * @param file
+     * @throws FileSystemException
+     */
+    void save(final RamFileObject file) throws FileSystemException
+    {
+
+        // Validate name
+        if (file.getData().getName() == null)
+        {
+            throw new FileSystemException(new IllegalStateException(
+                    "The data has no name. " + file));
+        }
+
+        // Add to the parent
+        if (file.getName().getDepth() > 0)
+        {
+            RamFileData parentData = (RamFileData) this.cache.get(file
+                    .getParent().getName());
+            // Only if not already added
+            if (!parentData.hasChildren(file.getData()))
+            {
+                RamFileObject parent = (RamFileObject) file.getParent();
+                parent.getData().addChild(file.getData());
+                parent.close();
+            }
+        }
+        // Store in cache
+        cache.put(file.getName(), file.getData());
+        file.getData().updateLastModified();
+        file.close();
+    }
+
+    /**
+     * @param from The original file.
+     * @param to The new file.
+     * @throws FileSystemException if an error occurs.
+     */
+    void rename(RamFileObject from, RamFileObject to)
+            throws FileSystemException
+    {
+        if (!this.cache.containsKey(from.getName()))
+        {
+            throw new FileSystemException("File does not exist: "
+                    + from.getName());
+        }
+        // Copy data
+
+        to.getData().setBuffer(from.getData().getBuffer());
+        to.getData().setLastModified(from.getData().getLastModified());
+        to.getData().setType(from.getData().getType());
+
+        this.save(to);
+        this.delete(from);
+    }
+
+    public void attach(RamFileObject fo)
+    {
+        if (fo.getName() == null)
+        {
+            throw new IllegalArgumentException("Null argument");
+        }
+        RamFileData data = (RamFileData) this.cache.get(fo.getName());
+        if (data == null)
+        {
+            data = new RamFileData(fo.getName());
+        }
+        fo.setData(data);
+    }
+
+    /**
+     * Import a Tree.
+     *
+     * @param file The File
+     * @throws FileSystemException if an error occurs.
+     */
+    public void importTree(File file) throws FileSystemException
+    {
+        FileObject fileFo = getFileSystemManager().toFileObject(file);
+        this.toRamFileObject(fileFo, fileFo);
+    }
+
+    /**
+     * Import the given file with the name relative to the given root
+     *
+     * @param fo
+     * @param root
+     * @throws FileSystemException
+     */
+    void toRamFileObject(FileObject fo, FileObject root)
+            throws FileSystemException
+    {
+        RamFileObject memFo = (RamFileObject) this.resolveFile(fo.getName()
+                .getPath().substring(root.getName().getPath().length()));
+        if (fo.getType().hasChildren())
+        {
+            // Create Folder
+            memFo.createFolder();
+            // Import recursively
+            FileObject[] fos = fo.getChildren();
+            for (int i = 0; i < fos.length; i++)
+            {
+                FileObject child = fos[i];
+                this.toRamFileObject(child, root);
+            }
+        }
+        else if (fo.getType().equals(FileType.FILE))
+        {
+            // Read bytes
+            try
+            {
+                InputStream is = fo.getContent().getInputStream();
+                try
+                {
+                    OutputStream os = new BufferedOutputStream(memFo
+                            .getOutputStream(), 512);
+                    int i;
+                    while ((i = is.read()) != -1)
+                    {
+                        os.write(i);
+                    }
+                    os.flush();
+                    os.close();
+                }
+                finally
+                {
+                    try
+                    {
+                        is.close();
+                    }
+                    catch (IOException e)
+                    {
+                        // ignore on close exception
+                    }
+                }
+            }
+            catch (IOException e)
+            {
+                throw new FileSystemException(e.getClass().getName() + " "
+                        + e.getMessage());
+            }
+        }
+        else
+        {
+            throw new FileSystemException("File is not a folder nor a file "
+                    + memFo);
+        }
+    }
+
+    /**
+     * @return Returns the size of the FileSystem
+     */
+    int size()
+    {
+        int size = 0;
+        synchronized(cache) {
+            Iterator iter = cache.values().iterator();
+            while (iter.hasNext())
+            {
+                RamFileData data = (RamFileData) iter.next();
+                size += data.size();
+            }
+        }
+        return size;
+    }
+
+    /**
+     * Close the RAMFileSystem.
+     */
+    public void close()
+    {
+        this.cache.clear();
+        super.close();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystemConfigBuilder.java
new file mode 100644
index 0000000..b1bb084
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/RamFileSystemConfigBuilder.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram;
+
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemOptions;
+
+/**
+ * Config Builder for the RAM filesystem.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public final class RamFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+
+    /** max size key. */
+    private static final String MAX_SIZE_KEY = "maxsize";
+
+    /** config builder singleton. */
+    private static final RamFileSystemConfigBuilder singleton = new RamFileSystemConfigBuilder();
+
+    /**
+     * Constructor
+     */
+    private RamFileSystemConfigBuilder()
+    {
+        super("ram.");
+    }
+
+    /**
+     * @return the config builder singleton
+     */
+    public static RamFileSystemConfigBuilder getInstance()
+    {
+        return singleton;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected Class getConfigClass()
+    {
+        return RamFileSystem.class;
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return The maximum size of the file.
+     * @see #setMaxSize
+     */
+    public int getMaxSize(FileSystemOptions opts)
+    {
+        return getInteger(opts, MAX_SIZE_KEY, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Sets the maximum size of the file system.
+     *
+     * @param opts The FileSystem options.
+     * @param sizeInBytes The maximum file size.
+     */
+    public void setMaxSize(FileSystemOptions opts, int sizeInBytes)
+    {
+        setParam(opts, MAX_SIZE_KEY, new Integer(sizeInBytes));
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/package.html
new file mode 100644
index 0000000..e4320ad
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/ram/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The RAM File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileProvider.java
new file mode 100644
index 0000000..c8cf902
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileProvider.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.res;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileProvider;
+import org.apache.commons.vfs.provider.UriParser;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * The Resource provider.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class ResourceFileProvider extends AbstractFileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.DISPATCHER
+    }));
+
+    public ResourceFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Locates a file object, by absolute URI.
+     * @param baseFile The base file.
+     * @param uri The URI of the file to locate.
+     * @param fileSystemOptions The FileSystem options.
+     * @return the FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject findFile(final FileObject baseFile,
+                               final String uri,
+                               final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        StringBuffer buf = new StringBuffer(80);
+        UriParser.extractScheme(uri, buf);
+        String resourceName = buf.toString();
+
+        ClassLoader cl = ResourceFileSystemConfigBuilder.getInstance().getClassLoader(fileSystemOptions);
+        if (cl == null)
+        {
+            cl = getClass().getClassLoader();
+        }
+        final URL url = cl.getResource(resourceName);
+
+        if (url == null)
+        {
+            throw new FileSystemException("vfs.provider.url/badly-formed-uri.error", uri);
+        }
+
+        FileObject fo = getContext().getFileSystemManager().resolveFile(url.toExternalForm());
+        return fo;
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return org.apache.commons.vfs.provider.res.ResourceFileSystemConfigBuilder.getInstance();
+    }
+
+    public void closeFileSystem(FileSystem filesystem)
+    {
+        // no filesystem created here - so nothing to do
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileSystemConfigBuilder.java
new file mode 100644
index 0000000..a9d3d72
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/ResourceFileSystemConfigBuilder.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.res;
+
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.url.UrlFileSystem;
+
+/**
+ * The config BUILDER for various ftp configuration options.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class ResourceFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    private static final ResourceFileSystemConfigBuilder BUILDER = new ResourceFileSystemConfigBuilder();
+
+    private ResourceFileSystemConfigBuilder()
+    {
+        super("resource.");
+    }
+
+    public static ResourceFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+
+    public void setClassLoader(FileSystemOptions opts, ClassLoader classLoader)
+    {
+        setParam(opts, ClassLoader.class.getName(), classLoader);
+    }
+
+    public ClassLoader getClassLoader(FileSystemOptions opts)
+    {
+        return (ClassLoader) getParam(opts, ClassLoader.class.getName());
+    }
+
+    protected Class getConfigClass()
+    {
+        return UrlFileSystem.class;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/package.html
new file mode 100644
index 0000000..3592f37
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/res/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Resource File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpClientFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpClientFactory.java
new file mode 100644
index 0000000..eaa25b5
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpClientFactory.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
+import com.jcraft.jsch.Proxy;
+import com.jcraft.jsch.ProxyHTTP;
+import com.jcraft.jsch.ProxySOCKS5;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.util.Os;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * Create a JSch Session instance.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class SftpClientFactory
+{
+    private static final String SSH_DIR_NAME = ".ssh";
+
+    private SftpClientFactory()
+    {
+    }
+
+    /**
+     * Creates a new connection to the server.
+     * @param hostname The name of the host to connect to.
+     * @param port The port to use.
+     * @param username The user's id.
+     * @param password The user's password.
+     * @param fileSystemOptions The FileSystem options.
+     * @return A Session.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static Session createConnection(String hostname, int port, char[] username, char[] password,
+                                           FileSystemOptions fileSystemOptions) throws FileSystemException
+    {
+        JSch jsch = new JSch();
+
+        File sshDir = null;
+
+        // new style - user passed
+        File knownHostsFile = SftpFileSystemConfigBuilder.getInstance().getKnownHosts(fileSystemOptions);
+        File[] identities = SftpFileSystemConfigBuilder.getInstance().getIdentities(fileSystemOptions);
+
+        if (knownHostsFile != null)
+        {
+            try
+            {
+                jsch.setKnownHosts(knownHostsFile.getAbsolutePath());
+            }
+            catch (JSchException e)
+            {
+                throw new FileSystemException("vfs.provider.sftp/known-hosts.error",
+                    knownHostsFile.getAbsolutePath(), e);
+            }
+        }
+        else
+        {
+            if (sshDir == null)
+            {
+                sshDir = findSshDir();
+            }
+            // Load the known hosts file
+            knownHostsFile = new File(sshDir, "known_hosts");
+            if (knownHostsFile.isFile() && knownHostsFile.canRead())
+            {
+                try
+                {
+                    jsch.setKnownHosts(knownHostsFile.getAbsolutePath());
+                }
+                catch (JSchException e)
+                {
+                    throw new FileSystemException("vfs.provider.sftp/known-hosts.error",
+                        knownHostsFile.getAbsolutePath(), e);
+                }
+            }
+        }
+
+        if (identities != null)
+        {
+            for (int iterIdentities = 0; iterIdentities < identities.length; iterIdentities++)
+            {
+                final File privateKeyFile = identities[iterIdentities];
+                try
+                {
+                    jsch.addIdentity(privateKeyFile.getAbsolutePath());
+                }
+                catch (final JSchException e)
+                {
+                    throw new FileSystemException("vfs.provider.sftp/load-private-key.error", privateKeyFile, e);
+                }
+            }
+        }
+        else
+        {
+            if (sshDir == null)
+            {
+                sshDir = findSshDir();
+            }
+
+            // Load the private key (rsa-key only)
+            final File privateKeyFile = new File(sshDir, "id_rsa");
+            if (privateKeyFile.isFile() && privateKeyFile.canRead())
+            {
+                try
+                {
+                    jsch.addIdentity(privateKeyFile.getAbsolutePath());
+                }
+                catch (final JSchException e)
+                {
+                    throw new FileSystemException("vfs.provider.sftp/load-private-key.error", privateKeyFile, e);
+                }
+            }
+        }
+
+        Session session;
+        try
+        {
+            session = jsch.getSession(new String(username),
+                    hostname,
+                    port);
+            if (password != null)
+            {
+                session.setPassword(new String(password));
+            }
+
+            Integer timeout = SftpFileSystemConfigBuilder.getInstance().getTimeout(fileSystemOptions);
+            if (timeout != null)
+            {
+                session.setTimeout(timeout.intValue());
+            }
+
+            UserInfo userInfo = SftpFileSystemConfigBuilder.getInstance().getUserInfo(fileSystemOptions);
+            if (userInfo != null)
+            {
+                session.setUserInfo(userInfo);
+            }
+
+            Properties config = new Properties();
+
+            //set StrictHostKeyChecking property
+            String strictHostKeyChecking =
+                SftpFileSystemConfigBuilder.getInstance().getStrictHostKeyChecking(fileSystemOptions);
+            if (strictHostKeyChecking != null)
+            {
+                config.setProperty("StrictHostKeyChecking", strictHostKeyChecking);
+            }
+            //set PreferredAuthentications property
+            String preferredAuthentications = SftpFileSystemConfigBuilder.getInstance().
+            getPreferredAuthentications(fileSystemOptions);
+            if (preferredAuthentications != null)
+            {
+                config.setProperty("PreferredAuthentications", preferredAuthentications);
+            }
+
+            //set compression property
+            String compression = SftpFileSystemConfigBuilder.getInstance().getCompression(fileSystemOptions);
+            if (compression != null)
+            {
+                config.setProperty("compression.s2c", compression);
+                config.setProperty("compression.c2s", compression);
+            }
+
+            String proxyHost = SftpFileSystemConfigBuilder.getInstance().getProxyHost(fileSystemOptions);
+            if (proxyHost != null)
+            {
+                int proxyPort = SftpFileSystemConfigBuilder.getInstance().getProxyPort(fileSystemOptions);
+                SftpFileSystemConfigBuilder.ProxyType proxyType =
+                    SftpFileSystemConfigBuilder.getInstance().getProxyType(fileSystemOptions);
+                Proxy proxy = null;
+                if (SftpFileSystemConfigBuilder.PROXY_HTTP.equals(proxyType))
+                {
+                    if (proxyPort != 0)
+                    {
+                        proxy = new ProxyHTTP(proxyHost, proxyPort);
+                    }
+                    else
+                    {
+                        proxy = new ProxyHTTP(proxyHost);
+                    }
+                }
+                else if (SftpFileSystemConfigBuilder.PROXY_SOCKS5.equals(proxyType))
+                {
+                    if (proxyPort != 0)
+                    {
+                        proxy = new ProxySOCKS5(proxyHost, proxyPort);
+                    }
+                    else
+                    {
+                        proxy = new ProxySOCKS5(proxyHost);
+                    }
+                }
+
+                if (proxy != null)
+                {
+                    session.setProxy(proxy);
+                }
+            }
+
+            //set properties for the session
+            if (config.size() > 0)
+            {
+                session.setConfig(config);
+            }
+            session.setDaemonThread(true);
+            session.connect();
+        }
+        catch (final Exception exc)
+        {
+            throw new FileSystemException("vfs.provider.sftp/connect.error", new Object[]{hostname}, exc);
+        }
+
+
+        return session;
+    }
+
+    /**
+     * Finds the .ssh directory.
+     * <p>The lookup order is:</p>
+     * <ol>
+     * <li>The system property <code>vfs.sftp.sshdir</code> (the override
+     * mechanism)</li>
+     * <li><code>{user.home}/.ssh</code></li>
+     * <li>On Windows only: C:\cygwin\home\{user.name}\.ssh</li>
+     * <li>The current directory, as a last resort.</li>
+     * <ol>
+     * <p/>
+     * Windows Notes:
+     * The default installation directory for Cygwin is <code>C:\cygwin</code>.
+     * On my set up (Gary here), I have Cygwin in C:\bin\cygwin, not the default.
+     * Also, my .ssh directory was created in the {user.home} directory.
+     * </p>
+     *
+     * @return The .ssh directory
+     */
+    private static File findSshDir()
+    {
+        String sshDirPath;
+        sshDirPath = System.getProperty("vfs.sftp.sshdir");
+        if (sshDirPath != null)
+        {
+            File sshDir = new File(sshDirPath);
+            if (sshDir.exists())
+            {
+                return sshDir;
+            }
+        }
+
+        File sshDir = new File(System.getProperty("user.home"), SSH_DIR_NAME);
+        if (sshDir.exists())
+        {
+            return sshDir;
+        }
+
+        if (Os.isFamily(Os.OS_FAMILY_WINDOWS))
+        {
+            // TODO - this may not be true
+            final String userName = System.getProperty("user.name");
+            sshDir = new File("C:\\cygwin\\home\\" + userName + "\\" + SSH_DIR_NAME);
+            if (sshDir.exists())
+            {
+                return sshDir;
+            }
+        }
+        return new File("");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileNameParser.java
new file mode 100644
index 0000000..0417c1d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileNameParser.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+
+
+/**
+ * Implementation for sftp. set default port to 22.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class SftpFileNameParser extends URLFileNameParser
+{
+    private static final SftpFileNameParser INSTANCE = new SftpFileNameParser();
+
+    public SftpFileNameParser()
+    {
+        super(22);
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java
new file mode 100644
index 0000000..09af8f0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileObject.java
@@ -0,0 +1,570 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.ChannelSftp.LsEntry;
+import com.jcraft.jsch.SftpATTRS;
+import com.jcraft.jsch.SftpException;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileNotFoundException;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.VFS;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.commons.vfs.util.MonitorInputStream;
+import org.apache.commons.vfs.util.MonitorOutputStream;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Vector;
+
+/**
+ * An SFTP file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date: 2005-10-14 19:59:47 +0200 (Fr, 14 Okt
+ *          2005) $
+ */
+public class SftpFileObject extends AbstractFileObject implements FileObject
+{
+    private final SftpFileSystem fileSystem;
+    private SftpATTRS attrs;
+    private final String relPath;
+
+    private boolean inRefresh;
+
+    protected SftpFileObject(final FileName name,
+            final SftpFileSystem fileSystem) throws FileSystemException
+    {
+        super(name, fileSystem);
+        this.fileSystem = fileSystem;
+        relPath = UriParser.decode(fileSystem.getRootName().getRelativeName(
+                name));
+    }
+
+    protected void doDetach() throws Exception
+    {
+        attrs = null;
+    }
+
+    public void refresh() throws FileSystemException
+    {
+        if (!inRefresh)
+        {
+            try
+            {
+                inRefresh = true;
+                super.refresh();
+                try
+                {
+                    attrs = null;
+                    getType();
+                }
+                catch (IOException e)
+                {
+                    throw new FileSystemException(e);
+                }
+            }
+            finally
+            {
+                inRefresh = false;
+            }
+        }
+    }
+
+    /**
+     * Determines the type of this file, returns null if the file does not
+     * exist.
+     */
+    protected FileType doGetType() throws Exception
+    {
+        if (attrs == null)
+        {
+            statSelf();
+        }
+
+        if (attrs == null)
+        {
+            return FileType.IMAGINARY;
+        }
+
+        if ((attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS) == 0)
+        {
+            throw new FileSystemException(
+                    "vfs.provider.sftp/unknown-permissions.error");
+        }
+        if (attrs.isDir())
+        {
+            return FileType.FOLDER;
+        }
+        else
+        {
+            return FileType.FILE;
+        }
+    }
+
+    /**
+     * Called when the type or content of this file changes.
+     */
+    protected void onChange() throws Exception
+    {
+        statSelf();
+    }
+
+    /**
+     * Fetches file attrs from server.
+     */
+    private void statSelf() throws Exception
+    {
+        ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            setStat(channel.stat(relPath));
+        }
+        catch (final SftpException e)
+        {
+            try
+            {
+                // maybe the channel has some problems, so recreate the channel and retry
+                if (e.id != ChannelSftp.SSH_FX_NO_SUCH_FILE)
+                {
+                    channel.disconnect();
+                    channel = fileSystem.getChannel();
+                    setStat(channel.stat(relPath));
+                }
+                else
+                {
+                    // Really does not exist
+                    attrs = null;
+                }
+            }
+            catch (final SftpException e2)
+            {
+                // TODO - not strictly true, but jsch 0.1.2 does not give us
+                // enough info in the exception. Should be using:
+                // if ( e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE )
+                // However, sometimes the exception has the correct id, and
+                // sometimes
+                // it does not. Need to look into why.
+
+                // Does not exist
+                attrs = null;
+            }
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * Set attrs from listChildrenResolved
+     */
+    private void setStat(SftpATTRS attrs)
+    {
+        this.attrs = attrs;
+    }
+
+    /**
+     * Creates this file as a folder.
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        final ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            channel.mkdir(relPath);
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        if (attrs == null
+                || (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_ACMODTIME) == 0)
+        {
+            throw new FileSystemException(
+                    "vfs.provider.sftp/unknown-modtime.error");
+        }
+        return attrs.getMTime() * 1000L;
+    }
+
+    /**
+     * Sets the last modified time of this file. Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}. <p/>
+     *
+     * @param modtime
+     *            is modification time in milliseconds. SFTP protocol can send
+     *            times with nanosecond precision but at the moment jsch send
+     *            them with second precision.
+     */
+    protected void doSetLastModifiedTime(final long modtime) throws Exception
+    {
+        final ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            int newMTime = (int) (modtime / 1000L);
+
+            attrs.setACMODTIME(attrs.getATime(), newMTime);
+            channel.setStat(relPath, attrs);
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * Deletes the file.
+     */
+    protected void doDelete() throws Exception
+    {
+        final ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            if (getType() == FileType.FILE)
+            {
+                channel.rm(relPath);
+            }
+            else
+            {
+                channel.rmdir(relPath);
+            }
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * Rename the file.
+     */
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        final ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            channel.rename(relPath, ((SftpFileObject) newfile).relPath);
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * Lists the children of this file.
+     */
+    protected FileObject[] doListChildrenResolved() throws Exception
+    {
+        // List the contents of the folder
+        Vector vector = null;
+        final ChannelSftp channel = fileSystem.getChannel();
+
+        try
+        {
+            // try the direct way to list the directory on the server to avoid too many roundtrips
+            vector = channel.ls(relPath);
+        }
+        catch (SftpException e)
+        {
+            String workingDirectory = null;
+            try
+            {
+                if (relPath != null)
+                {
+                    workingDirectory = channel.pwd();
+                    channel.cd(relPath);
+                }
+            }
+            catch (SftpException ex)
+            {
+                // VFS-210: seems not to be a directory
+                return null;
+            }
+
+            SftpException lsEx = null;
+            try
+            {
+                vector = channel.ls(".");
+            }
+            catch (SftpException ex)
+            {
+                lsEx = ex;
+            }
+            finally
+            {
+                try
+                {
+                    if (relPath != null)
+                    {
+                        channel.cd(workingDirectory);
+                    }
+                }
+                catch (SftpException xe)
+                {
+                    throw new FileSystemException("vfs.provider.sftp/change-work-directory-back.error", workingDirectory, lsEx);
+                }
+            }
+
+            if (lsEx != null)
+            {
+                throw lsEx;
+            }
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+        if (vector == null)
+        {
+            throw new FileSystemException(
+                    "vfs.provider.sftp/list-children.error");
+        }
+
+        // Extract the child names
+        final ArrayList children = new ArrayList();
+        for (Iterator iterator = vector.iterator(); iterator.hasNext();)
+        {
+            final LsEntry stat = (LsEntry) iterator.next();
+
+            String name = stat.getFilename();
+            if (VFS.isUriStyle())
+            {
+                if (stat.getAttrs().isDir()
+                        && name.charAt(name.length() - 1) != '/')
+                {
+                    name = name + "/";
+                }
+            }
+
+            if (name.equals(".") || name.equals("..") || name.equals("./")
+                    || name.equals("../"))
+            {
+                continue;
+            }
+
+            FileObject fo =
+                getFileSystem()
+                    .resolveFile(
+                            getFileSystem().getFileSystemManager().resolveName(
+                                    getName(), UriParser.encode(name),
+                                    NameScope.CHILD));
+
+            ((SftpFileObject) FileObjectUtils.getAbstractFileObject(fo)).setStat(stat.getAttrs());
+
+            children.add(fo);
+        }
+
+        return (FileObject[]) children.toArray(new FileObject[children
+                .size()]);
+    }
+
+    /**
+     * Lists the children of this file.
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        // use doListChildrenResolved for performance
+        return null;
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        if (attrs == null
+                || (attrs.getFlags() & SftpATTRS.SSH_FILEXFER_ATTR_SIZE) == 0)
+        {
+            throw new FileSystemException(
+                    "vfs.provider.sftp/unknown-size.error");
+        }
+        return attrs.getSize();
+    }
+
+    protected RandomAccessContent doGetRandomAccessContent(
+            final RandomAccessMode mode) throws Exception
+    {
+        return new SftpRandomAccessContent(this, mode);
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    InputStream getInputStream(long filePointer) throws IOException
+    {
+        final ChannelSftp channel = fileSystem.getChannel();
+        try
+        {
+            // hmmm - using the in memory method is soooo much faster ...
+            // TODO - Don't read the entire file into memory. Use the
+            // stream-based methods on ChannelSftp once they work properly final
+            // .... no stream based method with resume???
+            ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+            try
+            {
+                channel.get(getName().getPathDecoded(), outstr, null,
+                        ChannelSftp.RESUME, filePointer);
+            }
+            catch (SftpException e)
+            {
+                throw new FileSystemException(e);
+            }
+            outstr.close();
+            return new ByteArrayInputStream(outstr.toByteArray());
+        }
+        finally
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        // VFS-113: avoid npe
+        synchronized (fileSystem)
+        {
+            final ChannelSftp channel = fileSystem.getChannel();
+            try
+            {
+                // return channel.get(getName().getPath());
+                // hmmm - using the in memory method is soooo much faster ...
+
+                // TODO - Don't read the entire file into memory. Use the
+                // stream-based methods on ChannelSftp once they work properly
+
+                /*
+                final ByteArrayOutputStream outstr = new ByteArrayOutputStream();
+                channel.get(relPath, outstr);
+                outstr.close();
+                return new ByteArrayInputStream(outstr.toByteArray());
+                */
+
+                InputStream is;
+                try
+                {
+                    // VFS-210: sftp allows to gather an input stream even from a directory and will
+                    // fail on first read. So we need to check the type anyway
+                    if (!getType().hasContent())
+                    {
+                        throw new FileSystemException("vfs.provider/read-not-file.error", getName());
+                    }
+
+                    is = channel.get(relPath);
+                }
+                catch (SftpException e)
+                {
+                    if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE)
+                    {
+                        throw new FileNotFoundException(getName());
+                    }
+
+                    throw new FileSystemException(e);
+                }
+
+                return new SftpInputStream(channel, is);
+
+            }
+            finally
+            {
+//              fileSystem.putChannel(channel);
+            }
+        }
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        // TODO - Don't write the entire file into memory. Use the stream-based
+        // methods on ChannelSftp once the work properly
+        /*
+        final ChannelSftp channel = fileSystem.getChannel();
+        return new SftpOutputStream(channel);
+        */
+
+        final ChannelSftp channel = fileSystem.getChannel();
+        return new SftpOutputStream(channel, channel.put(relPath));
+    }
+
+    /**
+     * An InputStream that monitors for end-of-file.
+     */
+    private class SftpInputStream extends MonitorInputStream
+    {
+        private final ChannelSftp channel;
+
+        public SftpInputStream(final ChannelSftp channel, final InputStream in)
+        {
+            super(in);
+            this.channel = channel;
+        }
+
+        /**
+         * Called after the stream has been closed.
+         */
+        protected void onClose() throws IOException
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+    /**
+     * An OutputStream that wraps an sftp OutputStream, and closes the channel
+     * when the stream is closed.
+     */
+    private class SftpOutputStream extends MonitorOutputStream
+    {
+        private final ChannelSftp channel;
+
+        public SftpOutputStream(final ChannelSftp channel, OutputStream out)
+        {
+            super(out);
+            this.channel = channel;
+        }
+
+        /**
+         * Called after this stream is closed.
+         */
+        protected void onClose() throws IOException
+        {
+            fileSystem.putChannel(channel);
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileProvider.java
new file mode 100644
index 0000000..5872599
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileProvider.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.Session;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A provider for accessing files over SFTP.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Id$
+ */
+public class SftpFileProvider extends AbstractOriginatingFileProvider
+{
+    /** User Information. */
+    public static final String ATTR_USER_INFO = "UI";
+
+    /** Authentication types. */
+    public static final UserAuthenticationData.Type[] AUTHENTICATOR_TYPES =
+        new UserAuthenticationData.Type[]
+            {
+                UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD
+            };
+
+    /** The provider's capabilities. */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.CREATE,
+        Capability.DELETE,
+        Capability.RENAME,
+        Capability.GET_TYPE,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.WRITE_CONTENT,
+        Capability.GET_LAST_MODIFIED,
+        Capability.SET_LAST_MODIFIED_FILE,
+        Capability.RANDOM_ACCESS_READ
+    }));
+
+    // private JSch jSch = new JSch();
+
+    public SftpFileProvider()
+    {
+        super();
+        setFileNameParser(SftpFileNameParser.getInstance());
+    }
+
+    /**
+     * Creates a {@link FileSystem}.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // JSch jsch = createJSch(fileSystemOptions);
+
+        // Create the file system
+        final GenericFileName rootName = (GenericFileName) name;
+
+        Session session;
+        UserAuthenticationData authData = null;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(fileSystemOptions, AUTHENTICATOR_TYPES);
+
+            session = SftpClientFactory.createConnection(
+                rootName.getHostName(),
+                rootName.getPort(),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME,
+                    UserAuthenticatorUtils.toChar(rootName.getUserName())),
+                UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD,
+                    UserAuthenticatorUtils.toChar(rootName.getPassword())),
+                fileSystemOptions);
+        }
+        catch (final Exception e)
+        {
+            throw new FileSystemException("vfs.provider.sftp/connect.error",
+                name,
+                e);
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+
+        return new SftpFileSystem(rootName, session, fileSystemOptions);
+    }
+
+
+    /**
+     * Returns the JSch.
+     *
+     * @return Returns the jSch.
+     */
+    /*
+    private JSch getJSch()
+    {
+        return this.jSch;
+    }
+    */
+
+    /**
+     * Initialises the component.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return SftpFileSystemConfigBuilder.getInstance();
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystem.java
new file mode 100644
index 0000000..42cae7f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystem.java
@@ -0,0 +1,203 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpException;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * Represents the files on an SFTP server.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SftpFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+
+    private Session session;
+    // private final JSch jSch;
+    private ChannelSftp idleChannel;
+
+    protected SftpFileSystem(final GenericFileName rootName,
+                             final Session session,
+                             final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+        this.session = session;
+    }
+
+    protected void doCloseCommunicationLink()
+    {
+        if (idleChannel != null)
+        {
+            idleChannel.disconnect();
+            idleChannel = null;
+        }
+
+        if (session != null)
+        {
+            session.disconnect();
+            session = null;
+        }
+    }
+
+    /**
+     * Returns an SFTP channel to the server.
+     */
+    protected ChannelSftp getChannel() throws IOException
+    {
+        if (this.session == null || !this.session.isConnected())
+        {
+            doCloseCommunicationLink();
+
+            // channel closed. e.g. by freeUnusedResources, but now we need it again
+            Session session;
+            UserAuthenticationData authData = null;
+            try
+            {
+                final GenericFileName rootName = (GenericFileName) getRootName();
+
+                authData = UserAuthenticatorUtils.authenticate(getFileSystemOptions(),
+                    SftpFileProvider.AUTHENTICATOR_TYPES);
+
+                session = SftpClientFactory.createConnection(
+                    rootName.getHostName(),
+                    rootName.getPort(),
+                    UserAuthenticatorUtils.getData(authData, UserAuthenticationData.USERNAME,
+                        UserAuthenticatorUtils.toChar(rootName.getUserName())),
+                    UserAuthenticatorUtils.getData(authData, UserAuthenticationData.PASSWORD,
+                        UserAuthenticatorUtils.toChar(rootName.getPassword())),
+                    getFileSystemOptions());
+            }
+            catch (final Exception e)
+            {
+                throw new FileSystemException("vfs.provider.sftp/connect.error",
+                    getRootName(),
+                    e);
+            }
+            finally
+            {
+                UserAuthenticatorUtils.cleanup(authData);
+            }
+
+            this.session = session;
+        }
+
+        try
+        {
+            // Use the pooled channel, or create a new one
+            final ChannelSftp channel;
+            if (idleChannel != null)
+            {
+                channel = idleChannel;
+                idleChannel = null;
+            }
+            else
+            {
+                channel = (ChannelSftp) session.openChannel("sftp");
+                channel.connect();
+
+                Boolean userDirIsRoot =
+                    SftpFileSystemConfigBuilder.getInstance().getUserDirIsRoot(getFileSystemOptions());
+                String workingDirectory = getRootName().getPath();
+                if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue()))
+                {
+                    try
+                    {
+                        channel.cd(workingDirectory);
+                    }
+                    catch (SftpException e)
+                    {
+                        throw new FileSystemException("vfs.provider.sftp/change-work-directory.error",
+                            workingDirectory);
+                    }
+                }
+            }
+
+            return channel;
+        }
+        catch (final JSchException e)
+        {
+            throw new FileSystemException("vfs.provider.sftp/connect.error",
+                getRootName(),
+                e);
+        }
+    }
+
+    /**
+     * Returns a channel to the pool.
+     */
+    protected void putChannel(final ChannelSftp channel)
+    {
+        if (idleChannel == null)
+        {
+            // put back the channel only if it is still connected
+            if (channel.isConnected() && !channel.isClosed())
+            {
+                idleChannel = channel;
+            }
+        }
+        else
+        {
+            channel.disconnect();
+        }
+    }
+
+    /**
+     * Adds the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(SftpFileProvider.capabilities);
+    }
+
+    /**
+     * Creates a file object.  This method is called only if the requested
+     * file is not cached.
+     */
+    protected FileObject createFile(final FileName name)
+        throws FileSystemException
+    {
+        return new SftpFileObject(name, this);
+    }
+
+    /**
+     * last mod time is only a int and in seconds, thus can be off by 999.
+     *
+     * @return 1000
+     */
+    public double getLastModTimeAccuracy()
+    {
+        return 1000L;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystemConfigBuilder.java
new file mode 100644
index 0000000..e5429f8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpFileSystemConfigBuilder.java
@@ -0,0 +1,358 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.UserInfo;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * The config BUILDER for various sftp configuration options.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class SftpFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    /** HTTP Proxy. */
+    public static final ProxyType PROXY_HTTP = new ProxyType("http");
+    /** SOCKS Proxy. */
+    public static final ProxyType PROXY_SOCKS5 = new ProxyType("socks");
+
+    private static final SftpFileSystemConfigBuilder BUILDER = new SftpFileSystemConfigBuilder();
+    private static final String USER_DIR_IS_ROOT = SftpFileSystemConfigBuilder.class.getName() + ".USER_DIR_IS_ROOT";
+    private static final String TIMEOUT = SftpFileSystemConfigBuilder.class.getName() + ".TIMEOUT";
+
+    private SftpFileSystemConfigBuilder()
+    {
+        super("sftp.");
+    }
+
+    public static SftpFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * Proxy type.
+     */
+    public static final class ProxyType implements Serializable, Comparable
+    {
+        private final String proxyType;
+
+        private ProxyType(final String proxyType)
+        {
+            this.proxyType = proxyType;
+        }
+
+        public int compareTo(Object o)
+        {
+            return proxyType.compareTo(((ProxyType) o).proxyType);
+        }
+
+        public boolean equals(Object o)
+        {
+            if (this == o)
+            {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass())
+            {
+                return false;
+            }
+
+            ProxyType proxyType1 = (ProxyType) o;
+
+            if (proxyType != null ? !proxyType.equals(proxyType1.proxyType) : proxyType1.proxyType != null)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public int hashCode()
+        {
+            return proxyType.hashCode();
+        }
+    }
+
+    /**
+     * Set the userinfo class to use if e.g. a password or a not known host
+     * will be contacted.
+     *
+     * @param opts The FileSystem options.
+     * @param info User information.
+     */
+    public void setUserInfo(FileSystemOptions opts, UserInfo info)
+    {
+        setParam(opts, UserInfo.class.getName(), info);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return The UserInfo.
+     * @see #setUserInfo
+     */
+    public UserInfo getUserInfo(FileSystemOptions opts)
+    {
+        return (UserInfo) getParam(opts, UserInfo.class.getName());
+    }
+
+    /**
+     * Set the known_hosts file. e.g. /home/user/.ssh/known_hosts2<br>
+     * Need to use a java.io.File as JSch cant deal with vfs FileObjects ;-)
+     *
+     * @param opts The FileSystem options.
+     * @param sshdir The known hosts directory.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setKnownHosts(FileSystemOptions opts, File sshdir) throws FileSystemException
+    {
+        setParam(opts, "knownHosts", sshdir);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return the known hosts File.
+     * @see #setKnownHosts
+     */
+    public File getKnownHosts(FileSystemOptions opts)
+    {
+        return (File) getParam(opts, "knownHosts");
+    }
+
+    /**
+     * Set the identity files (your private key files).<br>
+     * Need to use a java.io.File as JSch cant deal with vfs FileObjects ;-)
+     *
+     * @param opts The FileSystem options.
+     * @param identities An array of identity Files.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setIdentities(FileSystemOptions opts, File[] identities) throws FileSystemException
+    {
+        setParam(opts, "identities", identities);
+    }
+
+    /**
+     * configure the compression to use.<br>
+     * e.g. pass "zlib,none" to enable the compression.<br>
+     * See the jsch documentation for details.
+     *
+     * @param opts The FileSystem options.
+     * @param compression The compression algorithm name.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setCompression(FileSystemOptions opts, String compression) throws FileSystemException
+    {
+        setParam(opts, "compression", compression);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return The name of the compression algorithm.
+     * @see #setCompression
+     */
+    public String getCompression(FileSystemOptions opts)
+    {
+        return getString(opts, "compression");
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return the array of identity Files.
+     * @see #setIdentities
+     */
+    public File[] getIdentities(FileSystemOptions opts)
+    {
+        return (File[]) getParam(opts, "identities");
+    }
+
+    /**
+     * configure the host key checking to use.<br>
+     * valid arguments are only yes, no and ask.<br>
+     * See the jsch documentation for details.
+     *
+     * @param opts The FileSystem options.
+     * @param hostKeyChecking The host key checking to use.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setStrictHostKeyChecking(FileSystemOptions opts, String hostKeyChecking) throws FileSystemException
+    {
+        if (hostKeyChecking == null || (!hostKeyChecking.equals("ask") && !hostKeyChecking.equals("no") &&
+            !hostKeyChecking.equals("yes")))
+        {
+            throw new FileSystemException("vfs.provider.sftp/StrictHostKeyChecking-arg.error", hostKeyChecking);
+        }
+
+        setParam(opts, "StrictHostKeyChecking", hostKeyChecking);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return the option value The host key checking.
+     * @see #setStrictHostKeyChecking(FileSystemOptions, String)
+     */
+    public String getStrictHostKeyChecking(FileSystemOptions opts)
+    {
+        return getString(opts, "StrictHostKeyChecking", "no");
+    }
+
+    /**
+     * use user directory as root (do not change to fs root).
+     *
+     * @param opts The FileSystem options.
+     * @param userDirIsRoot true if the user dir is the root directory.
+     */
+    public void setUserDirIsRoot(FileSystemOptions opts, boolean userDirIsRoot)
+    {
+        setParam(opts, USER_DIR_IS_ROOT, userDirIsRoot ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /**
+     * @param opts The FileSystemOptions.
+     * @return true if the user directory is the root.
+     * @see #setUserDirIsRoot
+     */
+    public Boolean getUserDirIsRoot(FileSystemOptions opts)
+    {
+        return getBoolean(opts, USER_DIR_IS_ROOT, Boolean.TRUE);
+    }
+
+    /**
+     * set the timeout value on jsch session.
+     *
+     * @param opts The FileSystem options.
+     * @param timeout The timeout.
+     */
+    public void setTimeout(FileSystemOptions opts, Integer timeout)
+    {
+        setParam(opts, TIMEOUT, timeout);
+    }
+
+    /**
+     * @param opts The FileSystem options.
+     * @return The timeout value.
+     * @see #setTimeout
+     */
+    public Integer getTimeout(FileSystemOptions opts)
+    {
+        return getInteger(opts, TIMEOUT);
+    }
+
+    protected Class getConfigClass()
+    {
+        return SftpFileSystem.class;
+    }
+
+    /**
+     * Set the proxy to use for sftp connection.<br>
+     * You have to set the ProxyPort too if you would like to have the proxy relly used.
+     *
+     * @param opts The FileSystem options.
+     * @param proxyHost the host
+     * @see #setProxyPort
+     */
+    public void setProxyHost(FileSystemOptions opts, String proxyHost)
+    {
+        setParam(opts, "proxyHost", proxyHost);
+    }
+
+    /**
+     * Set the proxy-port to use for sftp connection.
+     * You have to set the ProxyHost too if you would like to have the proxy relly used.
+     *
+     * @param opts The FileSystem options.
+     * @param proxyPort the port
+     * @see #setProxyHost
+     */
+    public void setProxyPort(FileSystemOptions opts, int proxyPort)
+    {
+        setParam(opts, "proxyPort", new Integer(proxyPort));
+    }
+
+    /**
+     * Get the proxy to use for sftp connection.
+     * You have to set the ProxyPort too if you would like to have the proxy relly used.
+     *
+     * @param opts The FileSystem options.
+     * @return proxyHost
+     * @see #setProxyPort
+     */
+    public String getProxyHost(FileSystemOptions opts)
+    {
+        return getString(opts, "proxyHost");
+    }
+
+    /**
+     * Get the proxy-port to use for sftp the connection
+     * You have to set the ProxyHost too if you would like to have the proxy relly used.
+     *
+     * @param opts The FileSystem options.
+     * @return proxyPort: the port number or 0 if it is not set
+     * @see #setProxyHost
+     */
+    public int getProxyPort(FileSystemOptions opts)
+    {
+        return getInteger(opts, "proxyPort", 0);
+    }
+
+    /**
+     * Set the proxy type to use for sftp connection.
+     * @param opts The FileSystem options.
+     * @param proxyType the type of the proxy to use.
+     */
+    public void setProxyType(FileSystemOptions opts, ProxyType proxyType)
+    {
+        setParam(opts, "proxyType", proxyType);
+    }
+
+    /**
+     * Get the proxy type to use for sftp connection.
+     * @param opts The FileSystem options.
+     * @return The ProxyType.
+     */
+    public ProxyType getProxyType(FileSystemOptions opts)
+    {
+        return (ProxyType) getParam(opts, "proxyType");
+    }
+
+    /**
+     * Configure authentication order.
+     * @param opts The FileSystem options.
+     * @param preferredAuthentications The authentication order.
+     */
+    public void setPreferredAuthentications(FileSystemOptions opts, String preferredAuthentications)
+    {
+        setParam(opts, "PreferredAuthentications", preferredAuthentications);
+    }
+
+    /**
+     * Get authentication order.
+     * @param opts The FileSystem options.
+     * @return The authentication order.
+     */
+    public String getPreferredAuthentications(FileSystemOptions opts)
+    {
+        return (String) getParam(opts, "PreferredAuthentications");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpRandomAccessContent.java
new file mode 100644
index 0000000..497b816
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/SftpRandomAccessContent.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractRandomAccessStreamContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.DataInputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Random access content.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+class SftpRandomAccessContent extends AbstractRandomAccessStreamContent
+{
+    /** file pointer */
+    protected long filePointer = 0;
+
+    private final SftpFileObject fileObject;
+    private DataInputStream dis = null;
+    private InputStream mis = null;
+
+    SftpRandomAccessContent(final SftpFileObject fileObject, RandomAccessMode mode)
+    {
+        super(mode);
+
+        this.fileObject = fileObject;
+        // fileSystem = (FtpFileSystem) this.fileObject.getFileSystem();
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return filePointer;
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        if (pos == filePointer)
+        {
+            // no change
+            return;
+        }
+
+        if (pos < 0)
+        {
+            throw new FileSystemException("vfs.provider/random-access-invalid-position.error",
+                new Object[]
+                {
+                    new Long(pos)
+                });
+        }
+        if (dis != null)
+        {
+            close();
+        }
+
+        filePointer = pos;
+    }
+
+    protected DataInputStream getDataInputStream() throws IOException
+    {
+        if (dis != null)
+        {
+            return dis;
+        }
+
+        // FtpClient client = fileSystem.getClient();
+        mis = fileObject.getInputStream(filePointer);
+        dis = new DataInputStream(new FilterInputStream(mis)
+        {
+            public int read() throws IOException
+            {
+                int ret = super.read();
+                if (ret > -1)
+                {
+                    filePointer++;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b) throws IOException
+            {
+                int ret = super.read(b);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+
+            public int read(byte[] b, int off, int len) throws IOException
+            {
+                int ret = super.read(b, off, len);
+                if (ret > -1)
+                {
+                    filePointer += ret;
+                }
+                return ret;
+            }
+
+            public void close() throws IOException
+            {
+                SftpRandomAccessContent.this.close();
+            }
+        });
+
+        return dis;
+    }
+
+
+    public void close() throws IOException
+    {
+        if (dis != null)
+        {
+            // mis.abort();
+            mis.close();
+
+            // this is to avoid recursive close
+            DataInputStream oldDis = dis;
+            dis = null;
+            oldDis.close();
+            mis = null;
+        }
+    }
+
+    public long length() throws IOException
+    {
+        return fileObject.getContent().getSize();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/TrustEveryoneUserInfo.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/TrustEveryoneUserInfo.java
new file mode 100644
index 0000000..ba6d8a3
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/TrustEveryoneUserInfo.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp;
+
+import com.jcraft.jsch.UserInfo;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Helper class to trust a new host.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class TrustEveryoneUserInfo implements UserInfo
+{
+    private final Log log = LogFactory.getLog(TrustEveryoneUserInfo.class);
+
+    public String getPassphrase()
+    {
+        return null;
+    }
+
+    public String getPassword()
+    {
+        return null;
+    }
+
+    public boolean promptPassword(String s)
+    {
+        log.info(s + " - Answer: False");
+        return false;
+    }
+
+    public boolean promptPassphrase(String s)
+    {
+        log.info(s + " - Answer: False");
+        return false;
+    }
+
+    public boolean promptYesNo(String s)
+    {
+        log.debug(s + " - Answer: Yes");
+
+        // trust
+        return true;
+    }
+
+    public void showMessage(String s)
+    {
+        log.debug(s);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/package.html
new file mode 100644
index 0000000..b88dc9a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/sftp/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The SFTP Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarBuffer.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarBuffer.java
new file mode 100644
index 0000000..79edc95
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarBuffer.java
@@ -0,0 +1,507 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+/**
+ * The TarBuffer class implements the tar archive concept of a buffered input
+ * stream. This concept goes back to the days of blocked tape drives and special
+ * io devices. In the Java universe, the only real function that this class
+ * performs is to ensure that files have the correct "block" size, or other tars
+ * will complain. <p>
+ * <p/>
+ * You should never have a need to access this class directly. TarBuffers are
+ * created by Tar IO Streams.
+ *
+ * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
+ * @author <a href="mailto:peter@apache.org">Peter Donald</a>
+ * @version $Revision$ $Date$
+ */
+class TarBuffer
+{
+    public static final int DEFAULT_RECORDSIZE = (512);
+    public static final int DEFAULT_BLOCKSIZE = (DEFAULT_RECORDSIZE * 20);
+
+    private byte[] blockBuffer;
+    private int blockSize;
+    private int currBlkIdx;
+    private int currRecIdx;
+    private boolean debug;
+
+    private InputStream input;
+    private OutputStream output;
+    private int recordSize;
+    private int recsPerBlock;
+
+    TarBuffer(final InputStream input)
+    {
+        this(input, TarBuffer.DEFAULT_BLOCKSIZE);
+    }
+
+    TarBuffer(final InputStream input, final int blockSize)
+    {
+        this(input, blockSize, TarBuffer.DEFAULT_RECORDSIZE);
+    }
+
+    TarBuffer(final InputStream input,
+              final int blockSize,
+              final int recordSize)
+    {
+        this.input = input;
+        initialize(blockSize, recordSize);
+    }
+
+    TarBuffer(final OutputStream output)
+    {
+        this(output, TarBuffer.DEFAULT_BLOCKSIZE);
+    }
+
+    TarBuffer(final OutputStream output, final int blockSize)
+    {
+        this(output, blockSize, TarBuffer.DEFAULT_RECORDSIZE);
+    }
+
+    TarBuffer(final OutputStream output,
+              final int blockSize,
+              final int recordSize)
+    {
+        this.output = output;
+        initialize(blockSize, recordSize);
+    }
+
+    /**
+     * Set the debugging flag for the buffer.
+     *
+     * @param debug If true, print debugging output.
+     */
+    public void setDebug(final boolean debug)
+    {
+        this.debug = debug;
+    }
+
+    /**
+     * Get the TAR Buffer's block size. Blocks consist of multiple records.
+     *
+     * @return The BlockSize value
+     */
+    public int getBlockSize()
+    {
+        return blockSize;
+    }
+
+    /**
+     * Get the current block number, zero based.
+     *
+     * @return The current zero based block number.
+     */
+    public int getCurrentBlockNum()
+    {
+        return currBlkIdx;
+    }
+
+    /**
+     * Get the current record number, within the current block, zero based.
+     * Thus, current offset = (currentBlockNum * recsPerBlk) + currentRecNum.
+     *
+     * @return The current zero based record number.
+     */
+    public int getCurrentRecordNum()
+    {
+        return currRecIdx - 1;
+    }
+
+    /**
+     * Get the TAR Buffer's record size.
+     *
+     * @return The RecordSize value
+     */
+    public int getRecordSize()
+    {
+        return recordSize;
+    }
+
+    /**
+     * Determine if an archive record indicate End of Archive. End of archive is
+     * indicated by a record that consists entirely of null bytes.
+     *
+     * @param record The record data to check.
+     * @return The EOFRecord value
+     */
+    public boolean isEOFRecord(final byte[] record)
+    {
+        final int size = getRecordSize();
+        for (int i = 0; i < size; ++i)
+        {
+            if (record[i] != 0)
+            {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Close the TarBuffer. If this is an output buffer, also flush the current
+     * block before closing.
+     */
+    public void close()
+            throws IOException
+    {
+        if (debug)
+        {
+            debug("TarBuffer.closeBuffer().");
+        }
+
+        if (null != output)
+        {
+            flushBlock();
+
+            if (output != System.out && output != System.err)
+            {
+                output.close();
+                output = null;
+            }
+        }
+        else if (input != null)
+        {
+            if (input != System.in)
+            {
+                input.close();
+                input = null;
+            }
+        }
+    }
+
+    /**
+     * Read a record from the input stream and return the data.
+     *
+     * @return The record data.
+     * @throws IOException Description of Exception
+     */
+    public byte[] readRecord()
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "ReadRecord: recIdx = " + currRecIdx +
+                    " blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == input)
+        {
+            final String message = "reading from an output buffer";
+            throw new IOException(message);
+        }
+
+        if (currRecIdx >= recsPerBlock)
+        {
+            if (!readBlock())
+            {
+                return null;
+            }
+        }
+
+        final byte[] result = new byte[recordSize];
+        System.arraycopy(blockBuffer,
+                (currRecIdx * recordSize),
+                result,
+                0,
+                recordSize);
+
+        currRecIdx++;
+
+        return result;
+    }
+
+    /**
+     * Skip over a record on the input stream.
+     */
+    public void skipRecord()
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "SkipRecord: recIdx = " + currRecIdx +
+                    " blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == input)
+        {
+            final String message = "reading (via skip) from an output buffer";
+            throw new IOException(message);
+        }
+
+        if (currRecIdx >= recsPerBlock)
+        {
+            if (!readBlock())
+            {
+                return; // UNDONE
+            }
+        }
+
+        currRecIdx++;
+    }
+
+    /**
+     * Write an archive record to the archive.
+     *
+     * @param record The record data to write to the archive.
+     */
+    public void writeRecord(final byte[] record)
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "WriteRecord: recIdx = " + currRecIdx +
+                    " blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == output)
+        {
+            final String message = "writing to an input buffer";
+            throw new IOException(message);
+        }
+
+        if (record.length != recordSize)
+        {
+            final String message = "record to write has length '" +
+                    record.length + "' which is not the record size of '" +
+                    recordSize + "'";
+            throw new IOException(message);
+        }
+
+        if (currRecIdx >= recsPerBlock)
+        {
+            writeBlock();
+        }
+
+        System.arraycopy(record,
+                0,
+                blockBuffer,
+                (currRecIdx * recordSize),
+                recordSize);
+
+        currRecIdx++;
+    }
+
+    /**
+     * Write an archive record to the archive, where the record may be inside of
+     * a larger array buffer. The buffer must be "offset plus record size" long.
+     *
+     * @param buffer The buffer containing the record data to write.
+     * @param offset The offset of the record data within buf.
+     */
+    public void writeRecord(final byte[] buffer, final int offset)
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "WriteRecord: recIdx = " + currRecIdx +
+                    " blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == output)
+        {
+            final String message = "writing to an input buffer";
+            throw new IOException(message);
+        }
+
+        if ((offset + recordSize) > buffer.length)
+        {
+            final String message = "record has length '" + buffer.length +
+                    "' with offset '" + offset + "' which is less than the record size of '" +
+                    recordSize + "'";
+            throw new IOException(message);
+        }
+
+        if (currRecIdx >= recsPerBlock)
+        {
+            writeBlock();
+        }
+
+        System.arraycopy(buffer,
+                offset,
+                blockBuffer,
+                (currRecIdx * recordSize),
+                recordSize);
+
+        currRecIdx++;
+    }
+
+    /**
+     * Flush the current data block if it has any data in it.
+     */
+    private void flushBlock()
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "TarBuffer.flushBlock() called.";
+            debug(message);
+        }
+
+        if (output == null)
+        {
+            final String message = "writing to an input buffer";
+            throw new IOException(message);
+        }
+
+        if (currRecIdx > 0)
+        {
+            writeBlock();
+        }
+    }
+
+    /**
+     * Initialization common to all constructors.
+     */
+    private void initialize(final int blockSize, final int recordSize)
+    {
+        debug = false;
+        this.blockSize = blockSize;
+        this.recordSize = recordSize;
+        recsPerBlock = (this.blockSize / this.recordSize);
+        blockBuffer = new byte[this.blockSize];
+
+        if (null != input)
+        {
+            currBlkIdx = -1;
+            currRecIdx = recsPerBlock;
+        }
+        else
+        {
+            currBlkIdx = 0;
+            currRecIdx = 0;
+        }
+    }
+
+    /**
+     * @return false if End-Of-File, else true
+     */
+    private boolean readBlock()
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "ReadBlock: blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == input)
+        {
+            final String message = "reading from an output buffer";
+            throw new IOException(message);
+        }
+
+        currRecIdx = 0;
+
+        int offset = 0;
+        int bytesNeeded = blockSize;
+
+        while (bytesNeeded > 0)
+        {
+            final long numBytes = input.read(blockBuffer, offset, bytesNeeded);
+
+            //
+            // NOTE
+            // We have fit EOF, and the block is not full!
+            //
+            // This is a broken archive. It does not follow the standard
+            // blocking algorithm. However, because we are generous, and
+            // it requires little effort, we will simply ignore the error
+            // and continue as if the entire block were read. This does
+            // not appear to break anything upstream. We used to return
+            // false in this case.
+            //
+            // Thanks to 'Yohann.Roussel@alcatel.fr' for this fix.
+            //
+            if (numBytes == -1)
+            {
+                // However, just leaving the unread portion of the buffer dirty does
+                // cause problems in some cases.  This problem is described in
+                // http://issues.apache.org/bugzilla/show_bug.cgi?id=29877
+                //
+                // The solution is to fill the unused portion of the buffer with zeros.
+
+                Arrays.fill(blockBuffer, offset, offset + bytesNeeded, (byte) 0);
+
+                break;
+            }
+
+            offset += numBytes;
+            bytesNeeded -= numBytes;
+
+            if (numBytes != blockSize)
+            {
+                if (debug)
+                {
+                    System.err.println("ReadBlock: INCOMPLETE READ "
+                            + numBytes + " of " + blockSize
+                            + " bytes read.");
+                }
+            }
+        }
+
+        currBlkIdx++;
+
+        return true;
+    }
+
+    /**
+     * Write a TarBuffer block to the archive.
+     *
+     * @throws IOException Description of Exception
+     */
+    private void writeBlock()
+            throws IOException
+    {
+        if (debug)
+        {
+            final String message = "WriteBlock: blkIdx = " + currBlkIdx;
+            debug(message);
+        }
+
+        if (null == output)
+        {
+            final String message = "writing to an input buffer";
+            throw new IOException(message);
+        }
+
+        output.write(blockBuffer, 0, blockSize);
+        output.flush();
+
+        currRecIdx = 0;
+        currBlkIdx++;
+    }
+
+    protected void debug(final String message)
+    {
+        if (debug)
+        {
+            System.err.println(message);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarConstants.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarConstants.java
new file mode 100644
index 0000000..9c60ac6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarConstants.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+/**
+ * This interface contains all the definitions used in the package.
+ *
+ * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @version $Revision$ $Date$
+ */
+interface TarConstants
+{
+    /**
+     * The length of the mode field in a header buffer.
+     */
+    int MODELEN = 8;
+
+    /**
+     * The length of the user id field in a header buffer.
+     */
+    int UIDLEN = 8;
+
+    /**
+     * The length of the group id field in a header buffer.
+     */
+    int GIDLEN = 8;
+
+    /**
+     * The length of the checksum field in a header buffer.
+     */
+    int CHKSUMLEN = 8;
+
+    /**
+     * The length of the size field in a header buffer.
+     */
+    int SIZELEN = 12;
+
+    /**
+     * The length of the magic field in a header buffer.
+     */
+    int MAGICLEN = 8;
+
+    /**
+     * The length of the modification time field in a header buffer.
+     */
+    int MODTIMELEN = 12;
+
+    /**
+     * The length of the user name field in a header buffer.
+     */
+    int UNAMELEN = 32;
+
+    /**
+     * The length of the group name field in a header buffer.
+     */
+    int GNAMELEN = 32;
+
+    /**
+     * The length of the devices field in a header buffer.
+     */
+    int DEVLEN = 8;
+
+    /**
+     * LF_ constants represent the "link flag" of an entry, or more commonly,
+     * the "entry type". This is the "old way" of indicating a normal file.
+     */
+    byte LF_OLDNORM = 0;
+
+    /**
+     * Normal file type.
+     */
+    byte LF_NORMAL = (byte) '0';
+
+    /**
+     * Link file type.
+     */
+    byte LF_LINK = (byte) '1';
+
+    /**
+     * Symbolic link file type.
+     */
+    byte LF_SYMLINK = (byte) '2';
+
+    /**
+     * Character device file type.
+     */
+    byte LF_CHR = (byte) '3';
+
+    /**
+     * Block device file type.
+     */
+    byte LF_BLK = (byte) '4';
+
+    /**
+     * Directory file type.
+     */
+    byte LF_DIR = (byte) '5';
+
+    /**
+     * FIFO (pipe) file type.
+     */
+    byte LF_FIFO = (byte) '6';
+
+    /**
+     * Contiguous file type.
+     */
+    byte LF_CONTIG = (byte) '7';
+
+    /**
+     * The magic tag representing a POSIX tar archive.
+     */
+    String TMAGIC = "ustar";
+
+    /**
+     * The magic tag representing a GNU tar archive.
+     */
+    String GNU_TMAGIC = "ustar  ";
+
+    /**
+     * The namr of the GNU tar entry which contains a long name.
+     */
+    String GNU_LONGLINK = "././@LongLink";
+
+    /**
+     * Identifies the *next* file on the tape as having a long name.
+     */
+    byte LF_GNUTYPE_LONGNAME = (byte) 'L';
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarEntry.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarEntry.java
new file mode 100644
index 0000000..53955c9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarEntry.java
@@ -0,0 +1,698 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * This class represents an entry in a Tar archive. It consists of the entry's
+ * header, as well as the entry's File. Entries can be instantiated in one of
+ * three ways, depending on how they are to be used. <p>
+ * <p/>
+ * TarEntries that are created from the header bytes read from an archive are
+ * instantiated with the TarEntry( byte[] ) constructor. These entries will be
+ * used when extracting from or listing the contents of an archive. These
+ * entries have their header filled in using the header bytes. They also set the
+ * File to null, since they reference an archive entry not a file. <p>
+ * <p/>
+ * TarEntries that are created from Files that are to be written into an archive
+ * are instantiated with the TarEntry( File ) constructor. These entries have
+ * their header filled in using the File's information. They also keep a
+ * reference to the File for convenience when writing entries. <p>
+ * <p/>
+ * Finally, TarEntries can be constructed from nothing but a name. This allows
+ * the programmer to construct the entry by hand, for instance when only an
+ * InputStream is available for writing to the archive, and the header
+ * information is constructed from other information. In this case the header
+ * fields are set to defaults and the File is set to null. <p>
+ * <p/>
+ * The C structure for a Tar Entry's header is: <pre>
+ * struct header {
+ * char name[NAMSIZ];
+ * char mode[8];
+ * char uid[8];
+ * char gid[8];
+ * char size[12];
+ * char mtime[12];
+ * char chksum[8];
+ * char linkflag;
+ * char linkname[NAMSIZ];
+ * char magic[8];
+ * char uname[TUNMLEN];
+ * char gname[TGNMLEN];
+ * char devmajor[8];
+ * char devminor[8];
+ * } header;
+ * </pre>
+ *
+ * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:peter@apache.org">Peter Donald</a>
+ * @version $Revision$ $Date$
+ * @see TarInputStream
+ */
+class TarEntry
+{
+    /**
+     * The length of the name field in a header buffer.
+     */
+    public static final int NAMELEN = 100;
+
+    /**
+     * The entry's modification time.
+     */
+    private int checkSum;
+
+    /**
+     * The entry's group name.
+     */
+    private int devMajor;
+
+    /**
+     * The entry's major device number.
+     */
+    private int devMinor;
+
+    /**
+     * The entry's minor device number.
+     */
+    private File file;
+
+    /**
+     * The entry's user id.
+     */
+    private int groupID;
+
+    /**
+     * The entry's user name.
+     */
+    private StringBuffer groupName;
+
+    /**
+     * The entry's checksum.
+     */
+    private byte linkFlag;
+
+    /**
+     * The entry's link flag.
+     */
+    private StringBuffer linkName;
+
+    /**
+     * The entry's link name.
+     */
+    private StringBuffer magic;
+
+    /**
+     * The entry's size.
+     */
+    private long modTime;
+
+    /**
+     * The entry's name.
+     */
+    private int mode;
+
+    private StringBuffer name;
+
+    /**
+     * The entry's group id.
+     */
+    private long size;
+
+    /**
+     * The entry's permission mode.
+     */
+    private int userID;
+
+    /**
+     * The entry's magic tag.
+     */
+    private StringBuffer userName;
+
+    /**
+     * Construct an entry with only a name. This allows the programmer to
+     * construct the entry's header "by hand". File is set to null.
+     *
+     * @param name the name of the entry
+     */
+    TarEntry(final String name)
+    {
+        this();
+
+        final boolean isDir = name.endsWith("/");
+
+        this.name = new StringBuffer(name);
+        mode = isDir ? 040755 : 0100644;
+        linkFlag = isDir ? TarConstants.LF_DIR : TarConstants.LF_NORMAL;
+        modTime = (new Date()).getTime() / 1000;
+        linkName = new StringBuffer("");
+        userName = new StringBuffer("");
+        groupName = new StringBuffer("");
+    }
+
+    /**
+     * Construct an entry with a name an a link flag.
+     *
+     * @param name     Description of Parameter
+     * @param linkFlag Description of Parameter
+     */
+    TarEntry(final String name, final byte linkFlag)
+    {
+        this(name);
+        this.linkFlag = linkFlag;
+    }
+
+    /**
+     * Construct an entry for a file. File is set to file, and the header is
+     * constructed from information from the file.
+     *
+     * @param file The file that the entry represents.
+     */
+    TarEntry(final File file)
+    {
+        this();
+
+        this.file = file;
+
+        String name = file.getPath();
+
+        // Strip off drive letters!
+        final String osName =
+                System.getProperty("os.name").toLowerCase(Locale.US);
+        if (-1 != osName.indexOf("netware"))
+        {
+            if (name.length() > 2)
+            {
+                final char ch1 = name.charAt(0);
+                final char ch2 = name.charAt(1);
+
+                if (ch2 == ':' &&
+                        ((ch1 >= 'a' && ch1 <= 'z') ||
+                                (ch1 >= 'A' && ch1 <= 'Z')))
+                {
+                    name = name.substring(2);
+                }
+            }
+        }
+        else if (-1 != osName.indexOf("netware"))
+        {
+            final int colon = name.indexOf(':');
+            if (colon != -1)
+            {
+                name = name.substring(colon + 1);
+            }
+        }
+
+        name = name.replace(File.separatorChar, '/');
+
+        // No absolute pathnames
+        // Windows (and Posix?) paths can start with "\\NetworkDrive\",
+        // so we loop on starting /'s.
+        while (name.startsWith("/"))
+        {
+            name = name.substring(1);
+        }
+
+        linkName = new StringBuffer("");
+        this.name = new StringBuffer(name);
+
+        if (file.isDirectory())
+        {
+            mode = 040755;
+            linkFlag = TarConstants.LF_DIR;
+
+            if (this.name.charAt(this.name.length() - 1) != '/')
+            {
+                this.name.append("/");
+            }
+        }
+        else
+        {
+            mode = 0100644;
+            linkFlag = TarConstants.LF_NORMAL;
+        }
+
+        size = file.length();
+        modTime = file.lastModified() / 1000;
+        checkSum = 0;
+        devMajor = 0;
+        devMinor = 0;
+    }
+
+    /**
+     * Construct an entry from an archive's header bytes. File is set to null.
+     *
+     * @param header The header bytes from a tar archive entry.
+     */
+    TarEntry(final byte[] header)
+    {
+        this();
+        parseTarHeader(header);
+    }
+
+    /**
+     * Construct an empty entry and prepares the header values.
+     */
+    private TarEntry()
+    {
+        magic = new StringBuffer(TarConstants.TMAGIC);
+        name = new StringBuffer();
+        linkName = new StringBuffer();
+
+        String user = System.getProperty("user.name", "");
+        if (user.length() > 31)
+        {
+            user = user.substring(0, 31);
+        }
+
+        userName = new StringBuffer(user);
+        groupName = new StringBuffer("");
+    }
+
+    /**
+     * Set this entry's group id.
+     *
+     * @param groupId This entry's new group id.
+     */
+    public void setGroupID(final int groupId)
+    {
+        groupID = groupId;
+    }
+
+    /**
+     * Set this entry's group id.
+     *
+     * @param groupId This entry's new group id.
+     * @see #setGroupID(int)
+     * @deprecated Use setGroupID() instead
+     */
+    public void setGroupId(final int groupId)
+    {
+        groupID = groupId;
+    }
+
+    /**
+     * Set this entry's group name.
+     *
+     * @param groupName This entry's new group name.
+     */
+    public void setGroupName(final String groupName)
+    {
+        this.groupName = new StringBuffer(groupName);
+    }
+
+    /**
+     * Set this entry's modification time. The parameter passed to this method
+     * is in "Java time".
+     *
+     * @param time This entry's new modification time.
+     */
+    public void setModTime(final long time)
+    {
+        modTime = time / 1000;
+    }
+
+    /**
+     * Set this entry's modification time.
+     *
+     * @param time This entry's new modification time.
+     */
+    public void setModTime(final Date time)
+    {
+        modTime = time.getTime() / 1000;
+    }
+
+    /**
+     * Set the mode for this entry
+     *
+     * @param mode The new Mode value
+     */
+    public void setMode(final int mode)
+    {
+        this.mode = mode;
+    }
+
+    /**
+     * Set this entry's name.
+     *
+     * @param name This entry's new name.
+     */
+    public void setName(final String name)
+    {
+        this.name = new StringBuffer(name);
+    }
+
+    /**
+     * Set this entry's file size.
+     *
+     * @param size This entry's new file size.
+     */
+    public void setSize(final long size)
+    {
+        this.size = size;
+    }
+
+    /**
+     * Set this entry's user id.
+     *
+     * @param userId This entry's new user id.
+     */
+    public void setUserID(final int userId)
+    {
+        userID = userId;
+    }
+
+    /**
+     * Set this entry's user id.
+     *
+     * @param userId This entry's new user id.
+     * @see #setUserID(int)
+     * @deprecated Use setUserID() instead
+     */
+    public void setUserId(final int userId)
+    {
+        userID = userId;
+    }
+
+    /**
+     * Set this entry's user name.
+     *
+     * @param userName This entry's new user name.
+     */
+    public void setUserName(final String userName)
+    {
+        this.userName = new StringBuffer(userName);
+    }
+
+    /**
+     * If this entry represents a file, and the file is a directory, return an
+     * array of TarEntries for this entry's children.
+     *
+     * @return An array of TarEntry's for this entry's children.
+     */
+    public TarEntry[] getDirectoryEntries()
+    {
+        if (null == file || !file.isDirectory())
+        {
+            return new TarEntry[0];
+        }
+
+        final String[] list = file.list();
+        final TarEntry[] result = new TarEntry[list.length];
+
+        for (int i = 0; i < list.length; ++i)
+        {
+            result[i] = new TarEntry(new File(file, list[i]));
+        }
+
+        return result;
+    }
+
+    /**
+     * Get this entry's file.
+     *
+     * @return This entry's file.
+     */
+    public File getFile()
+    {
+        return file;
+    }
+
+    /**
+     * Get this entry's group id.
+     *
+     * @return This entry's group id.
+     * @see #getGroupID()
+     * @deprecated Use getGroupID() instead
+     */
+    public int getGroupId()
+    {
+        return groupID;
+    }
+
+    /**
+     * Get this entry's group id.
+     *
+     * @return This entry's group id.
+     */
+    public int getGroupID()
+    {
+        return groupID;
+    }
+
+    /**
+     * Get this entry's group name.
+     *
+     * @return This entry's group name.
+     */
+    public String getGroupName()
+    {
+        return groupName.toString();
+    }
+
+    /**
+     * Set this entry's modification time.
+     *
+     * @return The ModTime value
+     */
+    public Date getModTime()
+    {
+        return new Date(modTime * 1000);
+    }
+
+    /**
+     * Get this entry's mode.
+     *
+     * @return This entry's mode.
+     */
+    public int getMode()
+    {
+        return mode;
+    }
+
+    /**
+     * Get this entry's name.
+     *
+     * @return This entry's name.
+     */
+    public String getName()
+    {
+        return name.toString();
+    }
+
+    /**
+     * Get this entry's file size.
+     *
+     * @return This entry's file size.
+     */
+    public long getSize()
+    {
+        return size;
+    }
+
+    /**
+     * Get this entry's checksum.
+     *
+     * @return This entry's checksum.
+     */
+    public int getCheckSum()
+    {
+        return checkSum;
+    }
+
+    /**
+     * Get this entry's user id.
+     *
+     * @return This entry's user id.
+     * @see #getUserID()
+     * @deprecated Use getUserID() instead
+     */
+    public int getUserId()
+    {
+        return userID;
+    }
+
+    /**
+     * Get this entry's user id.
+     *
+     * @return This entry's user id.
+     */
+    public int getUserID()
+    {
+        return userID;
+    }
+
+    /**
+     * Get this entry's user name.
+     *
+     * @return This entry's user name.
+     */
+    public String getUserName()
+    {
+        return userName.toString();
+    }
+
+    /**
+     * Determine if the given entry is a descendant of this entry. Descendancy
+     * is determined by the name of the descendant starting with this entry's
+     * name.
+     *
+     * @param desc Entry to be checked as a descendent of
+     * @return True if entry is a descendant of
+     */
+    public boolean isDescendent(final TarEntry desc)
+    {
+        return desc.getName().startsWith(getName());
+    }
+
+    /**
+     * Return whether or not this entry represents a directory.
+     *
+     * @return True if this entry is a directory.
+     */
+    public boolean isDirectory()
+    {
+        if (file != null)
+        {
+            return file.isDirectory();
+        }
+
+        if (linkFlag == TarConstants.LF_DIR)
+        {
+            return true;
+        }
+
+        if (getName().endsWith("/"))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Indicate if this entry is a GNU long name block
+     *
+     * @return true if this is a long name extension provided by GNU tar
+     */
+    public boolean isGNULongNameEntry()
+    {
+        return linkFlag == TarConstants.LF_GNUTYPE_LONGNAME &&
+                name.toString().equals(TarConstants.GNU_LONGLINK);
+    }
+
+    /**
+     * Determine if the two entries are equal. Equality is determined by the
+     * header names being equal.
+     *
+     * @param other Entry to be checked for equality.
+     * @return True if the entries are equal.
+     */
+    public boolean equals(final Object other)
+    {
+        if (!(other instanceof TarEntry))
+        {
+            return false;
+        }
+        TarEntry entry = (TarEntry) other;
+        return getName().equals(entry.getName());
+    }
+
+    public int hashCode()
+    {
+        return getName().hashCode();
+    }
+
+    /**
+     * Parse an entry's header information from a header buffer.
+     *
+     * @param header The tar entry header buffer to get information from.
+     */
+    private void parseTarHeader(final byte[] header)
+    {
+        int offset = 0;
+
+        name = TarUtils.parseName(header, offset, NAMELEN);
+        offset += NAMELEN;
+        mode = (int) TarUtils.parseOctal(header, offset, TarConstants.MODELEN);
+        offset += TarConstants.MODELEN;
+        userID = (int) TarUtils.parseOctal(header, offset, TarConstants.UIDLEN);
+        offset += TarConstants.UIDLEN;
+        groupID = (int) TarUtils.parseOctal(header, offset, TarConstants.GIDLEN);
+        offset += TarConstants.GIDLEN;
+        size = TarUtils.parseOctal(header, offset, TarConstants.SIZELEN);
+        offset += TarConstants.SIZELEN;
+        modTime = TarUtils.parseOctal(header, offset, TarConstants.MODTIMELEN);
+        offset += TarConstants.MODTIMELEN;
+        checkSum = (int) TarUtils.parseOctal(header, offset, TarConstants.CHKSUMLEN);
+        offset += TarConstants.CHKSUMLEN;
+        linkFlag = header[offset++];
+        linkName = TarUtils.parseName(header, offset, NAMELEN);
+        offset += NAMELEN;
+        magic = TarUtils.parseName(header, offset, TarConstants.MAGICLEN);
+        offset += TarConstants.MAGICLEN;
+        userName = TarUtils.parseName(header, offset, TarConstants.UNAMELEN);
+        offset += TarConstants.UNAMELEN;
+        groupName = TarUtils.parseName(header, offset, TarConstants.GNAMELEN);
+        offset += TarConstants.GNAMELEN;
+        devMajor = (int) TarUtils.parseOctal(header, offset, TarConstants.DEVLEN);
+        offset += TarConstants.DEVLEN;
+        devMinor = (int) TarUtils.parseOctal(header, offset, TarConstants.DEVLEN);
+    }
+
+    /**
+     * Write an entry's header information to a header buffer.
+     *
+     * @param buffer The tar entry header buffer to fill in.
+     */
+    public void writeEntryHeader(final byte[] buffer)
+    {
+        int offset = 0;
+
+        offset = TarUtils.getNameBytes(name, buffer, offset, NAMELEN);
+        offset = TarUtils.getOctalBytes(mode, buffer, offset, TarConstants.MODELEN);
+        offset = TarUtils.getOctalBytes(userID, buffer, offset, TarConstants.UIDLEN);
+        offset = TarUtils.getOctalBytes(groupID, buffer, offset, TarConstants.GIDLEN);
+        offset = TarUtils.getLongOctalBytes(size, buffer, offset, TarConstants.SIZELEN);
+        offset = TarUtils.getLongOctalBytes(modTime, buffer, offset, TarConstants.MODTIMELEN);
+
+        final int checkSumOffset = offset;
+        for (int i = 0; i < TarConstants.CHKSUMLEN; ++i)
+        {
+            buffer[offset++] = (byte) ' ';
+        }
+
+        buffer[offset++] = linkFlag;
+        offset = TarUtils.getNameBytes(linkName, buffer, offset, NAMELEN);
+        offset = TarUtils.getNameBytes(magic, buffer, offset, TarConstants.MAGICLEN);
+        offset = TarUtils.getNameBytes(userName, buffer, offset, TarConstants.UNAMELEN);
+        offset = TarUtils.getNameBytes(groupName, buffer, offset, TarConstants.GNAMELEN);
+        offset = TarUtils.getOctalBytes(devMajor, buffer, offset, TarConstants.DEVLEN);
+        offset = TarUtils.getOctalBytes(devMinor, buffer, offset, TarConstants.DEVLEN);
+
+        while (offset < buffer.length)
+        {
+            buffer[offset++] = 0;
+        }
+
+        final long checkSum = TarUtils.computeCheckSum(buffer);
+        TarUtils.getCheckSumOctalBytes(checkSum, buffer, checkSumOffset, TarConstants.CHKSUMLEN);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileObject.java
new file mode 100644
index 0000000..1845074
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileObject.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+//TODO: Revert to [compress]
+//import org.apache.commons.compress.tar.TarEntry;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+
+import java.io.InputStream;
+import java.util.HashSet;
+
+/**
+ * A file in a Tar file system.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class TarFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    /** The TarEntry */
+    protected TarEntry entry;
+    private final HashSet children = new HashSet();
+    private final TarFileSystem fs;
+    private FileType type;
+
+    protected TarFileObject(FileName name,
+                            TarEntry entry,
+                            TarFileSystem fs,
+                            boolean tarExists) throws FileSystemException
+    {
+        super(name, fs);
+        this.fs = fs;
+        setTarEntry(entry);
+        if (!tarExists)
+        {
+            type = FileType.IMAGINARY;
+        }
+    }
+
+    /**
+     * Sets the details for this file object.
+     */
+    protected void setTarEntry(final TarEntry entry)
+    {
+        if (this.entry != null)
+        {
+            return;
+        }
+
+        if ((entry == null) || (entry.isDirectory()))
+        {
+            type = FileType.FOLDER;
+        }
+        else
+        {
+            type = FileType.FILE;
+        }
+
+        this.entry = entry;
+    }
+
+    /**
+     * Attaches a child
+     */
+    protected void attachChild(FileName childName)
+    {
+        children.add(childName.getBaseName());
+    }
+
+    /**
+     * Determines if this file can be written to.
+     *
+     * @return <code>true</code> if this file is writeable, <code>false</code> if not.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isWriteable() throws FileSystemException
+    {
+        return false;
+    }
+
+    /**
+     * Returns the file's type.
+     */
+    protected FileType doGetType()
+    {
+        return type;
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren()
+    {
+        try
+        {
+            if (!getType().hasChildren())
+            {
+                return null;
+            }
+        }
+        catch (FileSystemException e)
+        {
+            // should not happen as the type has already been cached.
+            throw new RuntimeException(e);
+        }
+
+        return (String[]) children.toArray(new String[children.size()]);
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).  Is only called if
+     * {@link #doGetType} returns {@link FileType#FILE}.
+     */
+    protected long doGetContentSize()
+    {
+        if (entry == null)
+        {
+            return 0;
+        }
+
+        return entry.getSize();
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        if (entry == null)
+        {
+            return 0;
+        }
+
+        return entry.getModTime().getTime();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.  Is only called
+     * if  {@link #doGetType} returns {@link FileType#FILE}.  The input stream
+     * returned by this method is guaranteed to be closed before this
+     * method is called again.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        // VFS-210: zip allows to gather an input stream even from a directory and will
+        // return -1 on the first read. getType should not be expensive and keeps the tests
+        // running
+        if (!getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/read-not-file.error", getName());
+        }
+
+        return fs.getInputStream(entry);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileProvider.java
new file mode 100644
index 0000000..8cb40d0
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileProvider.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractLayeredFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.LayeredFileName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A file system provider for Tar files.  Provides read-only file systems.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class TarFileProvider
+    extends AbstractLayeredFileProvider
+    implements FileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+        {
+            Capability.GET_LAST_MODIFIED,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT,
+            Capability.URI,
+            Capability.VIRTUAL
+        }));
+
+    public TarFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Creates a layered file system.  This method is called if the file system
+     * is not cached.
+     *
+     * @param scheme The URI scheme.
+     * @param file   The file to create the file system on top of.
+     * @return The file system.
+     */
+    protected FileSystem doCreateFileSystem(final String scheme,
+                                            final FileObject file,
+                                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        final FileName rootName =
+            new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
+        return new TarFileSystem(rootName, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileSystem.java
new file mode 100644
index 0000000..11db84f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarFileSystem.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+//TODO: Revert to [compress]
+//import org.apache.commons.compress.tar.TarEntry;
+//import org.apache.commons.compress.tar.TarInputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.bzip2.Bzip2FileObject;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * A read-only file system for Tar files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class TarFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    private static final Log LOG = LogFactory.getLog(TarFileSystem.class);
+
+    private final File file;
+    private TarInputStream tarFile;
+
+    protected TarFileSystem(final FileName rootName,
+                            final FileObject parentLayer,
+                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+
+        // Make a local copy of the file
+        file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
+
+        // Open the Tar file
+        if (!file.exists())
+        {
+            // Don't need to do anything
+            tarFile = null;
+            return;
+        }
+
+        // tarFile = createTarFile(this.file);
+    }
+
+    public void init() throws FileSystemException
+    {
+        super.init();
+
+        // Build the index
+        try
+        {
+            List strongRef = new ArrayList(100);
+            TarEntry entry;
+            while ((entry = getTarFile().getNextEntry()) != null)
+            {
+                FileName name = getFileSystemManager().resolveName(getRootName(), UriParser.encode(entry.getName()));
+
+                // Create the file
+                TarFileObject fileObj;
+                if (entry.isDirectory() && getFileFromCache(name) != null)
+                {
+                    fileObj = (TarFileObject) getFileFromCache(name);
+                    fileObj.setTarEntry(entry);
+                    continue;
+                }
+
+                fileObj = createTarFileObject(name, entry);
+                putFileToCache(fileObj);
+                strongRef.add(fileObj);
+                fileObj.holdObject(strongRef);
+
+                // Make sure all ancestors exist
+                // TODO - create these on demand
+                TarFileObject parent = null;
+                for (FileName parentName = name.getParent();
+                     parentName != null;
+                     fileObj = parent, parentName = parentName.getParent())
+                {
+                    // Locate the parent
+                    parent = (TarFileObject) getFileFromCache(parentName);
+                    if (parent == null)
+                    {
+                        parent = createTarFileObject(parentName, null);
+                        putFileToCache(parent);
+                        strongRef.add(parent);
+                        parent.holdObject(strongRef);
+                    }
+
+                    // Attach child to parent
+                    parent.attachChild(fileObj.getName());
+                }
+            }
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+        finally
+        {
+            closeCommunicationLink();
+        }
+    }
+
+    public InputStream getInputStream(TarEntry entry) throws FileSystemException
+    {
+        resetTarFile();
+        try
+        {
+            while (!tarFile.getNextEntry().equals(entry))
+            {
+            }
+            return tarFile;
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+    }
+
+    protected void resetTarFile() throws FileSystemException
+    {
+        // Reading specific entries requires skipping through the tar file from the beginning
+        // Not especially elegant, but we don't have the ability to seek to specific positions
+        // with an input stream.
+        if (this.file.exists())
+        {
+            recreateTarFile();
+        }
+    }
+
+    private void recreateTarFile() throws FileSystemException
+    {
+        if (this.tarFile != null)
+        {
+            try
+            {
+                this.tarFile.close();
+            }
+            catch (IOException e)
+            {
+                throw new FileSystemException("vfs.provider.tar/close-tar-file.error", file, e);
+            }
+            tarFile = null;
+        }
+        TarInputStream tarFile = createTarFile(this.file);
+        this.tarFile = tarFile;
+    }
+
+    protected TarInputStream getTarFile() throws FileSystemException
+    {
+        if (tarFile == null && this.file.exists())
+        {
+            recreateTarFile();
+        }
+
+        return tarFile;
+    }
+
+    protected TarFileObject createTarFileObject(final FileName name,
+                                                final TarEntry entry) throws FileSystemException
+    {
+        return new TarFileObject(name, entry, this, true);
+    }
+
+    protected TarInputStream createTarFile(final File file) throws FileSystemException
+    {
+        try
+        {
+            if ("tgz".equalsIgnoreCase(getRootName().getScheme()))
+            {
+                return new TarInputStream(new GZIPInputStream(new FileInputStream(file)));
+            }
+            else if ("tbz2".equalsIgnoreCase(getRootName().getScheme()))
+            {
+                return new TarInputStream(Bzip2FileObject.wrapInputStream(file.getAbsolutePath(),
+                    new FileInputStream(file)));
+            }
+            return new TarInputStream(new FileInputStream(file));
+        }
+        catch (IOException ioe)
+        {
+            throw new FileSystemException("vfs.provider.tar/open-tar-file.error", file, ioe);
+        }
+    }
+
+    protected void doCloseCommunicationLink()
+    {
+        // Release the tar file
+        try
+        {
+            if (tarFile != null)
+            {
+                tarFile.close();
+                tarFile = null;
+            }
+        }
+        catch (final IOException e)
+        {
+            // getLogger().warn("vfs.provider.tar/close-tar-file.error :" + file, e);
+            VfsLog.warn(getLogger(), LOG, "vfs.provider.tar/close-tar-file.error :" + file, e);
+        }
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(TarFileProvider.capabilities);
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name) throws FileSystemException
+    {
+        // This is only called for files which do not exist in the Tar file
+        return new TarFileObject(name, null, this, false);
+    }
+
+    /**
+     * will be called after all file-objects closed their streams.
+    protected void notifyAllStreamsClosed()
+    {
+        closeCommunicationLink();
+    }
+     */
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarInputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarInputStream.java
new file mode 100644
index 0000000..9024a27
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarInputStream.java
@@ -0,0 +1,492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * The TarInputStream reads a UNIX tar archive as an InputStream. methods are
+ * provided to position at each successive entry in the archive, and the read
+ * each entry as a normal input stream using read().
+ *
+ * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:peter@apache.org">Peter Donald</a>
+ * @version $Revision$ $Date$
+ * @see TarInputStream
+ * @see TarEntry
+ */
+class TarInputStream
+        extends FilterInputStream
+{
+    private TarBuffer buffer;
+    private TarEntry currEntry;
+    private boolean debug;
+    private int entryOffset;
+    private long entrySize;
+    private boolean hasHitEOF;
+    private byte[] oneBuf;
+    private byte[] readBuf;
+
+    /**
+     * Construct a TarInputStream using specified input
+     * stream and default block and record sizes.
+     *
+     * @param input stream to create TarInputStream from
+     * @see TarBuffer#DEFAULT_BLOCKSIZE
+     * @see TarBuffer#DEFAULT_RECORDSIZE
+     */
+    TarInputStream(final InputStream input)
+    {
+        this(input, TarBuffer.DEFAULT_BLOCKSIZE, TarBuffer.DEFAULT_RECORDSIZE);
+    }
+
+    /**
+     * Construct a TarInputStream using specified input
+     * stream, block size and default record sizes.
+     *
+     * @param input     stream to create TarInputStream from
+     * @param blockSize the block size to use
+     * @see TarBuffer#DEFAULT_RECORDSIZE
+     */
+    TarInputStream(final InputStream input,
+                   final int blockSize)
+    {
+        this(input, blockSize, TarBuffer.DEFAULT_RECORDSIZE);
+    }
+
+    /**
+     * Construct a TarInputStream using specified input
+     * stream, block size and record sizes.
+     *
+     * @param input      stream to create TarInputStream from
+     * @param blockSize  the block size to use
+     * @param recordSize the record size to use
+     */
+    TarInputStream(final InputStream input,
+                   final int blockSize,
+                   final int recordSize)
+    {
+        super(input);
+
+        buffer = new TarBuffer(input, blockSize, recordSize);
+        oneBuf = new byte[1];
+    }
+
+    /**
+     * Sets the debugging flag.
+     *
+     * @param debug The new Debug value
+     */
+    public void setDebug(final boolean debug)
+    {
+        this.debug = debug;
+        buffer.setDebug(debug);
+    }
+
+    /**
+     * Get the next entry in this tar archive. This will skip over any remaining
+     * data in the current entry, if there is one, and place the input stream at
+     * the header of the next entry, and read the header and instantiate a new
+     * TarEntry from the header bytes and return that entry. If there are no
+     * more entries in the archive, null will be returned to indicate that the
+     * end of the archive has been reached.
+     *
+     * @return The next TarEntry in the archive, or null.
+     * @throws IOException Description of Exception
+     */
+    public TarEntry getNextEntry()
+            throws IOException
+    {
+        if (hasHitEOF)
+        {
+            return null;
+        }
+
+        if (currEntry != null)
+        {
+            final long numToSkip = entrySize - entryOffset;
+
+            if (debug)
+            {
+                final String message = "TarInputStream: SKIP currENTRY '" +
+                        currEntry.getName() + "' SZ " + entrySize +
+                        " OFF " + entryOffset + "  skipping " + numToSkip + " bytes";
+                debug(message);
+            }
+
+            if (numToSkip > 0)
+            {
+                // Use our internal skip to move to the end of the current entry
+                longSkip(numToSkip);
+            }
+
+            readBuf = null;
+        }
+
+        final byte[] headerBuf = buffer.readRecord();
+        if (headerBuf == null)
+        {
+            if (debug)
+            {
+                debug("READ NULL RECORD");
+            }
+            hasHitEOF = true;
+        }
+        else if (buffer.isEOFRecord(headerBuf))
+        {
+            if (debug)
+            {
+                debug("READ EOF RECORD");
+            }
+            hasHitEOF = true;
+        }
+
+        if (hasHitEOF)
+        {
+            currEntry = null;
+        }
+        else
+        {
+            currEntry = new TarEntry(headerBuf);
+
+            if (!(headerBuf[257] == 'u' && headerBuf[258] == 's' &&
+                    headerBuf[259] == 't' && headerBuf[260] == 'a' &&
+                    headerBuf[261] == 'r'))
+            {
+                //Must be v7Format
+            }
+
+            if (debug)
+            {
+                final String message = "TarInputStream: SET CURRENTRY '" +
+                        currEntry.getName() + "' size = " + currEntry.getSize();
+                debug(message);
+            }
+
+            entryOffset = 0;
+
+            entrySize = currEntry.getSize();
+        }
+
+        if (null != currEntry && currEntry.isGNULongNameEntry())
+        {
+            // read in the name
+            final StringBuffer longName = new StringBuffer();
+            final byte[] buffer = new byte[256];
+            int length = 0;
+            while ((length = read(buffer)) >= 0)
+            {
+                final String str = new String(buffer, 0, length);
+                longName.append(str);
+            }
+            getNextEntry();
+
+            // remove trailing null terminator
+            if (longName.length() > 0
+                    && longName.charAt(longName.length() - 1) == 0)
+            {
+                longName.deleteCharAt(longName.length() - 1);
+            }
+
+            currEntry.setName(longName.toString());
+        }
+
+        return currEntry;
+    }
+
+    /**
+     * Get the record size being used by this stream's TarBuffer.
+     *
+     * @return The TarBuffer record size.
+     */
+    public int getRecordSize()
+    {
+        return buffer.getRecordSize();
+    }
+
+    /**
+     * Get the available data that can be read from the current entry in the
+     * archive. This does not indicate how much data is left in the entire
+     * archive, only in the current entry. This value is determined from the
+     * entry's size header field and the amount of data already read from the
+     * current entry.
+     *
+     * @return The number of available bytes for the current entry.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public int available()
+            throws IOException
+    {
+      long remaining = entrySize - entryOffset;
+      
+      if(remaining > Integer.MAX_VALUE) {
+        return Integer.MAX_VALUE;
+      }
+      
+      return (int) remaining;
+    }
+
+    /**
+     * Closes this stream. Calls the TarBuffer's close() method.
+     *
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public void close()
+            throws IOException
+    {
+        buffer.close();
+    }
+
+    /**
+     * Copies the contents of the current tar archive entry directly into an
+     * output stream.
+     *
+     * @param output The OutputStream into which to write the entry's data.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public void copyEntryContents(final OutputStream output)
+            throws IOException
+    {
+        final byte[] buffer = new byte[32 * 1024];
+        while (true)
+        {
+            final int numRead = read(buffer, 0, buffer.length);
+            if (numRead == -1)
+            {
+                break;
+            }
+
+            output.write(buffer, 0, numRead);
+        }
+    }
+
+    /**
+     * Since we do not support marking just yet, we do nothing.
+     *
+     * @param markLimit The limit to mark.
+     */
+    public void mark(int markLimit)
+    {
+    }
+
+    /**
+     * Since we do not support marking just yet, we return false.
+     *
+     * @return False.
+     */
+    public boolean markSupported()
+    {
+        return false;
+    }
+
+    /**
+     * Reads a byte from the current tar archive entry. This method simply calls
+     * read( byte[], int, int ).
+     *
+     * @return The byte read, or -1 at EOF.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public int read()
+            throws IOException
+    {
+        final int num = read(oneBuf, 0, 1);
+        if (num == -1)
+        {
+            return num;
+        }
+        else
+        {
+            return oneBuf[0];
+        }
+    }
+
+    /**
+     * Reads bytes from the current tar archive entry. This method simply calls
+     * read( byte[], int, int ).
+     *
+     * @param buffer The buffer into which to place bytes read.
+     * @return The number of bytes read, or -1 at EOF.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public int read(final byte[] buffer)
+            throws IOException
+    {
+        return read(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Reads bytes from the current tar archive entry. This method is aware of
+     * the boundaries of the current entry in the archive and will deal with
+     * them as if they were this stream's start and EOF.
+     *
+     * @param buffer The buffer into which to place bytes read.
+     * @param offset The offset at which to place bytes read.
+     * @param count  The number of bytes to read.
+     * @return The number of bytes read, or -1 at EOF.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public int read(final byte[] buffer,
+                    final int offset,
+                    final int count)
+            throws IOException
+    {
+        int position = offset;
+        int numToRead = count;
+        int totalRead = 0;
+
+        if (entryOffset >= entrySize)
+        {
+            return -1;
+        }
+
+        if ((numToRead + entryOffset) > entrySize)
+        {
+            numToRead = (int)(entrySize - entryOffset);
+        }
+
+        if (null != readBuf)
+        {
+            final int size =
+                    (numToRead > readBuf.length) ? readBuf.length : numToRead;
+
+            System.arraycopy(readBuf, 0, buffer, position, size);
+
+            if (size >= readBuf.length)
+            {
+                readBuf = null;
+            }
+            else
+            {
+                final int newLength = readBuf.length - size;
+                final byte[] newBuffer = new byte[newLength];
+
+                System.arraycopy(readBuf, size, newBuffer, 0, newLength);
+
+                readBuf = newBuffer;
+            }
+
+            totalRead += size;
+            numToRead -= size;
+            position += size;
+        }
+
+        while (numToRead > 0)
+        {
+            final byte[] rec = this.buffer.readRecord();
+            if (null == rec)
+            {
+                // Unexpected EOF!
+                final String message =
+                        "unexpected EOF with " + numToRead + " bytes unread";
+                throw new IOException(message);
+            }
+
+            int size = numToRead;
+            final int recordLength = rec.length;
+
+            if (recordLength > size)
+            {
+                System.arraycopy(rec, 0, buffer, position, size);
+
+                readBuf = new byte[recordLength - size];
+
+                System.arraycopy(rec, size, readBuf, 0, recordLength - size);
+            }
+            else
+            {
+                size = recordLength;
+
+                System.arraycopy(rec, 0, buffer, position, recordLength);
+            }
+
+            totalRead += size;
+            numToRead -= size;
+            position += size;
+        }
+
+        entryOffset += totalRead;
+
+        return totalRead;
+    }
+
+    /**
+     * Since we do not support marking just yet, we do nothing.
+     */
+    public void reset()
+    {
+    }
+
+    public void longSkip(final long numToSkip) throws IOException {
+      for(long skipped = 0; skipped < numToSkip;) {
+        if(numToSkip - skipped > Integer.MAX_VALUE) {
+          skip(Integer.MAX_VALUE);
+          skipped += Integer.MAX_VALUE;
+        } else {
+          skip((int)(numToSkip - skipped));
+          skipped += numToSkip - skipped;
+        }
+      }
+    }
+    
+    /**
+     * Skip bytes in the input buffer. This skips bytes in the current entry's
+     * data, not the entire archive, and will stop at the end of the current
+     * entry's data if the number to skip extends beyond that point.
+     *
+     * @param numToSkip The number of bytes to skip.
+     * @throws IOException when an IO error causes operation to fail
+     */
+    public void skip(final int numToSkip)
+            throws IOException
+    {
+        // REVIEW
+        // This is horribly inefficient, but it ensures that we
+        // properly skip over bytes via the TarBuffer...
+        //
+        final byte[] skipBuf = new byte[8 * 1024];
+        int num = numToSkip;
+        while (num > 0)
+        {
+            final int count = (num > skipBuf.length) ? skipBuf.length : num;
+            final int numRead = read(skipBuf, 0, count);
+            if (numRead == -1)
+            {
+                break;
+            }
+
+            num -= numRead;
+        }
+    }
+
+    /**
+     * Utility method to do debugging.
+     * Capable of being overidden in sub-classes.
+     *
+     * @param message the message to use in debugging
+     */
+    protected void debug(final String message)
+    {
+        if (debug)
+        {
+            System.err.println(message);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarUtils.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarUtils.java
new file mode 100644
index 0000000..52d7439
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TarUtils.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+/**
+ * This class provides static utility methods to work with byte streams.
+ *
+ * @author <a href="mailto:time@ice.com">Timothy Gerard Endres</a>
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @version $Revision$ $Date$
+ */
+final class TarUtils
+{
+    /**
+     * Private constructor since this is a utility class with only static methods.
+     */
+    private TarUtils()
+    {
+    }
+
+    /**
+     * Parse the checksum octal integer from a header buffer.
+     *
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @param value  Description of Parameter
+     * @param buf    Description of Parameter
+     * @return The integer value of the entry's checksum.
+     */
+    public static int getCheckSumOctalBytes(final long value,
+                                            final byte[] buf,
+                                            final int offset,
+                                            final int length)
+    {
+        getOctalBytes(value, buf, offset, length);
+
+        buf[offset + length - 1] = (byte) ' ';
+        buf[offset + length - 2] = 0;
+
+        return offset + length;
+    }
+
+    /**
+     * Parse an octal long integer from a header buffer.
+     *
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @param value  Description of Parameter
+     * @param buf    Description of Parameter
+     * @return The long value of the octal bytes.
+     */
+    public static int getLongOctalBytes(final long value,
+                                        final byte[] buf,
+                                        final int offset,
+                                        final int length)
+    {
+        byte[] temp = new byte[length + 1];
+
+        getOctalBytes(value, temp, 0, length + 1);
+        System.arraycopy(temp, 0, buf, offset, length);
+
+        return offset + length;
+    }
+
+    /**
+     * Determine the number of bytes in an entry name.
+     *
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @param name   Description of Parameter
+     * @param buffer Description of Parameter
+     * @return The number of bytes in a header's entry name.
+     */
+    public static int getNameBytes(final StringBuffer name,
+                                   final byte[] buffer,
+                                   final int offset,
+                                   final int length)
+    {
+        int i;
+
+        for (i = 0; i < length && i < name.length(); ++i)
+        {
+            buffer[offset + i] = (byte) name.charAt(i);
+        }
+
+        for (; i < length; ++i)
+        {
+            buffer[offset + i] = 0;
+        }
+
+        return offset + length;
+    }
+
+    /**
+     * Parse an octal integer from a header buffer.
+     *
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @return The integer value of the octal bytes.
+     */
+    public static int getOctalBytes(final long value,
+                                    final byte[] buffer,
+                                    final int offset,
+                                    final int length)
+    {
+        int idx = length - 1;
+
+        buffer[offset + idx] = 0;
+        --idx;
+        buffer[offset + idx] = (byte) ' ';
+        --idx;
+
+        if (value == 0)
+        {
+            buffer[offset + idx] = (byte) '0';
+            --idx;
+        }
+        else
+        {
+            long val = value;
+            while (idx >= 0 && val > 0)
+            {
+                buffer[offset + idx] = (byte) ((byte) '0' + (byte) (val & 7));
+                val = val >> 3;
+                idx--;
+            }
+        }
+
+        while (idx >= 0)
+        {
+            buffer[offset + idx] = (byte) ' ';
+            idx--;
+        }
+
+        return offset + length;
+    }
+
+    /**
+     * Compute the checksum of a tar entry header.
+     *
+     * @param buffer The tar entry's header buffer.
+     * @return The computed checksum.
+     */
+    public static long computeCheckSum(final byte[] buffer)
+    {
+        long sum = 0;
+
+        for (int i = 0; i < buffer.length; ++i)
+        {
+            sum += 255 & buffer[i];
+        }
+
+        return sum;
+    }
+
+    /**
+     * Parse an entry name from a header buffer.
+     *
+     * @param header The header buffer from which to parse.
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @return The header's entry name.
+     */
+    public static StringBuffer parseName(final byte[] header,
+                                         final int offset,
+                                         final int length)
+    {
+        StringBuffer result = new StringBuffer(length);
+        int end = offset + length;
+
+        for (int i = offset; i < end; ++i)
+        {
+            if (header[i] == 0)
+            {
+                break;
+            }
+
+            result.append((char) header[i]);
+        }
+
+        return result;
+    }
+
+    /**
+     * Parse an octal string from a header buffer. This is used for the file
+     * permission mode value.
+     *
+     * @param header The header buffer from which to parse.
+     * @param offset The offset into the buffer from which to parse.
+     * @param length The number of header bytes to parse.
+     * @return The long value of the octal string.
+     */
+    public static long parseOctal(final byte[] header,
+                                  final int offset,
+                                  final int length)
+    {
+        long result = 0;
+        boolean stillPadding = true;
+        int end = offset + length;
+
+        for (int i = offset; i < end; ++i)
+        {
+            if (header[i] == 0)
+            {
+                break;
+            }
+
+            if (header[i] == (byte) ' ' || header[i] == '0')
+            {
+                if (stillPadding)
+                {
+                    continue;
+                }
+
+                if (header[i] == (byte) ' ')
+                {
+                    break;
+                }
+            }
+
+            stillPadding = false;
+            result = (result << 3) + (header[i] - '0');
+        }
+
+        return result;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/Tbz2FileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/Tbz2FileProvider.java
new file mode 100644
index 0000000..8856cd2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/Tbz2FileProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import org.apache.commons.vfs.provider.CompositeFileProvider;
+
+import java.util.Collection;
+
+/**
+ * A file system provider for Tar files.  Provides read-only file systems.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class Tbz2FileProvider extends CompositeFileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities = TarFileProvider.capabilities;
+
+    private static final String[] SCHEMES = new String[]
+    {
+        "bz2",
+        "tar"
+    };
+
+    public Tbz2FileProvider()
+    {
+        super();
+    }
+
+    protected String[] getSchemes()
+    {
+        return SCHEMES;
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TgzFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TgzFileProvider.java
new file mode 100644
index 0000000..f726418
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/TgzFileProvider.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar;
+
+import org.apache.commons.vfs.provider.CompositeFileProvider;
+
+import java.util.Collection;
+
+/**
+ * A file system provider for Tar files.  Provides read-only file systems.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class TgzFileProvider extends CompositeFileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities = TarFileProvider.capabilities;
+
+    private static final String[] SCHEMES = new String[]
+    {
+        "gz",
+        "tar"
+    };
+
+    public TgzFileProvider()
+    {
+        super();
+    }
+
+    protected String[] getSchemes()
+    {
+        return SCHEMES;
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/package.html
new file mode 100644
index 0000000..a70bf44
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/tar/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Tar File Provider.</p>
+</body>
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java
new file mode 100644
index 0000000..0b4c4fe
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/TemporaryFileProvider.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.temp;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+import org.apache.commons.vfs.provider.local.LocalFileSystem;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * A provider for temporary files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class TemporaryFileProvider
+    extends AbstractFileProvider
+    implements FileProvider, Comparable
+{
+    private File rootFile;
+
+    /*
+    private final static FileName tmpFileName = new AbstractFileName("tmp", "/")
+    {
+        protected FileName createName(String absPath)
+        {
+            return null;
+        }
+
+        protected void appendRootUri(StringBuffer buffer)
+        {
+        }
+    };
+*/
+
+    public TemporaryFileProvider(final File rootFile)
+    {
+        this();
+
+        this.rootFile = rootFile;
+    }
+
+    public TemporaryFileProvider()
+    {
+        super();
+    }
+
+    public int compareTo(Object o)
+    {
+        int h1 = hashCode();
+        int h2 = o.hashCode();
+        if (h1 < h2)
+        {
+            return -1;
+        }
+        if (h1 > h2)
+        {
+            return 1;
+        }
+
+        return 0;
+    }
+
+    /**
+     * Locates a file object, by absolute URI.
+     * @param baseFile The base FileObject.
+     * @param uri The URI of the file to be located.
+     * @param properties FileSystemOptions to use to locate or create the file.
+     * @return The FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public synchronized FileObject findFile(final FileObject baseFile, final String uri,
+                                            final FileSystemOptions properties)
+        throws FileSystemException
+    {
+        // Parse the name
+        final StringBuffer buffer = new StringBuffer(uri);
+        final String scheme = UriParser.extractScheme(uri, buffer);
+
+        UriParser.fixSeparators(buffer);
+
+        FileType fileType = UriParser.normalisePath(buffer);
+        final String path = buffer.toString();
+
+        // Create the temp file system if it does not exist
+        // FileSystem filesystem = findFileSystem( this, (Properties) null);
+        FileSystem filesystem = findFileSystem(this, properties);
+        if (filesystem == null)
+        {
+            if (rootFile == null)
+            {
+                rootFile = getContext().getTemporaryFileStore().allocateFile("tempfs");
+            }
+            final FileName rootName =
+                getContext().parseURI(scheme + ":" + FileName.ROOT_PATH);
+            // final FileName rootName =
+            //    new LocalFileName(scheme, scheme + ":", FileName.ROOT_PATH);
+            filesystem = new LocalFileSystem(rootName, rootFile.getAbsolutePath(), properties);
+            addFileSystem(this, filesystem);
+        }
+
+        // Find the file
+        return filesystem.resolveFile(path);
+    }
+
+    public Collection getCapabilities()
+    {
+        return DefaultLocalFileProvider.capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/package.html
new file mode 100644
index 0000000..5249940
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/temp/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Temporary Filespace Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileName.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileName.java
new file mode 100644
index 0000000..d636c84
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileName.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url;
+
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.URLFileName;
+
+/**
+ * A URL FileName.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class UrlFileName extends URLFileName
+{
+    /**
+     * The constructor.
+     * @param scheme The scheme to use.
+     * @param hostName The host name.
+     * @param port The port.
+     * @param defaultPort The default port.
+     * @param userName The user's login id.
+     * @param password The user's credentials.
+     * @param path The file path.
+     * @param type The file type.
+     * @param queryString Parameters to use when locating or creating the file name.
+     */
+    public UrlFileName(final String scheme, final String hostName, final int port, final int defaultPort,
+                       final String userName, final String password, final String path, final FileType type,
+                       final String queryString)
+    {
+        super(scheme, hostName, port, defaultPort, userName, password, path, type, queryString);
+    }
+
+    protected void appendRootUri(final StringBuffer buffer, boolean addPassword)
+    {
+        if (getHostName() != null && !"".equals(getHostName()))
+        {
+            super.appendRootUri(buffer, addPassword);
+            return;
+        }
+
+        buffer.append(getScheme());
+        buffer.append(":");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileNameParser.java
new file mode 100644
index 0000000..eef25cd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileNameParser.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractFileNameParser;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+import org.apache.commons.vfs.provider.local.GenericFileNameParser;
+
+/**
+ * Implementation for any java.net.url based filesystem.<br />
+ * Composite of URLFilenameParser and GenericFilenameParser
+ *
+ * @author imario@apache.org
+ * @version $Revision$ $Date$
+ */
+public class UrlFileNameParser extends AbstractFileNameParser
+{
+    private final URLFileNameParser url = new URLFileNameParser(80);
+    private final GenericFileNameParser generic = new GenericFileNameParser();
+
+    public UrlFileNameParser()
+    {
+        super();
+    }
+
+    public boolean encodeCharacter(char ch)
+    {
+        return super.encodeCharacter(ch) || ch == '?';
+    }
+
+  /**
+   * Parse a URI.
+   * @param context The component context.
+   * @param base The base FileName.
+   * @param filename The target file name.
+   * @return The FileName.
+   * @throws FileSystemException if an error occurs
+   */
+    public FileName parseUri(final VfsComponentContext context, final FileName base, final String filename)
+        throws FileSystemException
+    {
+        if (isUrlBased(base, filename))
+        {
+            return url.parseUri(context, base, filename);
+        }
+
+        return generic.parseUri(context, base, filename);
+    }
+
+    /**
+     * Guess is the given filename is a url with host or not. VFS treats such urls differently.<br />
+     * A filename is url-based if the base is a <code>URLFileName</code> or there are only 2 slashes
+     * after the scheme.<br/>
+     * e.g: http://host/path, file:/path/to/file, file:///path/to/file
+     *
+     */
+    protected boolean isUrlBased(final FileName base, final String filename)
+    {
+        if (base instanceof URLFileName)
+        {
+            return true;
+        }
+
+        int nuofSlash = countSlashes(filename);
+        return nuofSlash == 2;
+    }
+
+    /**
+     * This method counts the slashes after the scheme.
+     *
+     * @param filename The file name.
+     * @return number of slashes
+     */
+    protected int countSlashes(final String filename)
+    {
+        int state = 0;
+        int nuofSlash = 0;
+        for (int pos = 0; pos < filename.length(); pos++)
+        {
+            char c = filename.charAt(pos);
+            if (state == 0)
+            {
+                if (c >= 'a' && c <= 'z')
+                {
+                    continue;
+                }
+                if (c == ':')
+                {
+                    state++;
+                    continue;
+                }
+            }
+            else if (state == 1)
+            {
+                if (c == '/')
+                {
+                    nuofSlash++;
+                }
+                else
+                {
+                    return nuofSlash;
+                }
+            }
+        }
+        return nuofSlash;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileObject.java
new file mode 100644
index 0000000..5114baa
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileObject.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url;
+
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.URLFileName;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * A {@link FileObject} implementation backed by a {@link URL}.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Implement set lastModified and get/set attribute
+ * @todo Implement getOutputStream()
+ */
+public class UrlFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    private URL url;
+
+    protected UrlFileObject(final UrlFileSystem fs,
+                            final FileName fileName)
+    {
+        super(fileName, fs);
+    }
+
+    /**
+     * Attaches this file object to its file resource.  This method is called
+     * before any of the doBlah() or onBlah() methods.  Sub-classes can use
+     * this method to perform lazy initialisation.
+     */
+    protected void doAttach() throws Exception
+    {
+        if (url == null)
+        {
+            // url = new URL(getName().getURI());
+            url = createURL(getName());
+        }
+    }
+
+    protected URL createURL(final FileName name) throws MalformedURLException, FileSystemException, URIException
+    {
+        if (name instanceof URLFileName)
+        {
+            URLFileName urlName = (URLFileName) getName();
+
+            // TODO: charset
+            return new URL(urlName.getURIEncoded(null));
+        }
+        return new URL(getName().getURI());
+    }
+
+    /**
+     * Determines the type of the file.
+     */
+    protected FileType doGetType() throws Exception
+    {
+        try
+        {
+            // Attempt to connect & check status
+            final URLConnection conn = url.openConnection();
+            final InputStream in = conn.getInputStream();
+            try
+            {
+                if (conn instanceof HttpURLConnection)
+                {
+                    final int status = ((HttpURLConnection) conn).getResponseCode();
+                    // 200 is good, maybe add more later...
+                    if (HttpURLConnection.HTTP_OK != status)
+                    {
+                        return FileType.IMAGINARY;
+                    }
+                }
+
+                return FileType.FILE;
+            }
+            finally
+            {
+                in.close();
+            }
+        }
+        catch (final FileNotFoundException e)
+        {
+            return FileType.IMAGINARY;
+        }
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        final URLConnection conn = url.openConnection();
+        final InputStream in = conn.getInputStream();
+        try
+        {
+            return conn.getContentLength();
+        }
+        finally
+        {
+            in.close();
+        }
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime()
+        throws Exception
+    {
+        final URLConnection conn = url.openConnection();
+        final InputStream in = conn.getInputStream();
+        try
+        {
+            return conn.getLastModified();
+        }
+        finally
+        {
+            in.close();
+        }
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        throw new FileSystemException("Not implemented.");
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        return url.openStream();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileProvider.java
new file mode 100644
index 0000000..e999d77
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileProvider.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileProvider;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A file provider backed by Java's URL API.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlFileProvider
+    extends AbstractFileProvider
+{
+    /** The provider's capabilities */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.GET_LAST_MODIFIED
+    }));
+
+    public UrlFileProvider()
+    {
+        super();
+        setFileNameParser(new UrlFileNameParser());
+    }
+
+    /**
+     * Locates a file object, by absolute URI.
+     * @param baseFile The base FileObject.
+     * @param uri The uri of the file to locate.
+     * @param fileSystemOptions The FileSystemOptions
+     * @return The FileObject
+     * @throws FileSystemException if an error occurs.
+     */
+    public synchronized FileObject findFile(final FileObject baseFile,
+                                            final String uri,
+                                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        try
+        {
+            final URL url = new URL(uri);
+
+            URL rootUrl = new URL(url, "/");
+            final String key = this.getClass().getName() + rootUrl.toString();
+            FileSystem fs = findFileSystem(key, fileSystemOptions);
+            if (fs == null)
+            {
+                String extForm = rootUrl.toExternalForm();
+                final FileName rootName =
+                    getContext().parseURI(extForm);
+                // final FileName rootName =
+                //    new BasicFileName(rootUrl, FileName.ROOT_PATH);
+                fs = new UrlFileSystem(rootName, fileSystemOptions);
+                addFileSystem(key, fs);
+            }
+            return fs.resolveFile(url.getPath());
+        }
+        catch (final MalformedURLException e)
+        {
+            throw new FileSystemException("vfs.provider.url/badly-formed-uri.error", uri, e);
+        }
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return org.apache.commons.vfs.provider.res.ResourceFileSystemConfigBuilder.getInstance();
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileSystem.java
new file mode 100644
index 0000000..8909ff7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/UrlFileSystem.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.util.Collection;
+
+/**
+ * A File system backed by Java's URL API.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    protected UrlFileSystem(final FileName rootName, final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name)
+    {
+        return new UrlFileObject(this, name);
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(UrlFileProvider.capabilities);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/package.html
new file mode 100644
index 0000000..69b62bf
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/url/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Default File Provider, which wraps java.net.URL.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/ExceptionConverter.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/ExceptionConverter.java
new file mode 100644
index 0000000..1755642
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/ExceptionConverter.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.client.methods.DavMethod;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.commons.vfs.FileSystemException;
+import org.w3c.dom.Element;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * <code>ExceptionConverter</code> converts WebDAV exceptions into FileSystemExceptions.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public final class ExceptionConverter
+{
+    // avoid instanciation
+    private ExceptionConverter()
+    {
+    }
+
+    public static FileSystemException generate(DavException davExc) throws FileSystemException
+    {
+        return generate(davExc, null);
+    }
+
+    public static FileSystemException generate(DavException davExc, DavMethod method)
+            throws FileSystemException
+    {
+        String msg = davExc.getMessage();
+        if (davExc.hasErrorCondition())
+        {
+            try
+            {
+                Element error = davExc.toXml(DomUtil.BUILDER_FACTORY.newDocumentBuilder().newDocument());
+                if (DomUtil.matches(error, DavException.XML_ERROR, DavConstants.NAMESPACE))
+                {
+                    if (DomUtil.hasChildElement(error, "exception", null))
+                    {
+                        Element exc = DomUtil.getChildElement(error, "exception", null);
+                        if (DomUtil.hasChildElement(exc, "message", null))
+                        {
+                            msg = DomUtil.getChildText(exc, "message", null);
+                        }
+                        if (DomUtil.hasChildElement(exc, "class", null))
+                        {
+                            Class cl = Class.forName(DomUtil.getChildText(exc, "class", null));
+                            Constructor excConstr = cl.getConstructor(new Class[]{String.class});
+                            if (excConstr != null)
+                            {
+                                Object o = excConstr.newInstance(new String[]{msg});
+                                if (o instanceof FileSystemException)
+                                {
+                                    return (FileSystemException) o;
+                                }
+                                else if (o instanceof Exception)
+                                {
+                                    return new FileSystemException(msg, (Exception) o);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                throw new FileSystemException(e);
+            }
+        }
+
+        return new FileSystemException(msg);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileContentInfoFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileContentInfoFactory.java
new file mode 100644
index 0000000..9a288de
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileContentInfoFactory.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.DefaultFileContentInfo;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+
+/**
+ * Determines the content information for files accessed via WebDAV.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$
+ */
+public class WebdavFileContentInfoFactory implements FileContentInfoFactory
+{
+    public FileContentInfo create(FileContent fileContent) throws FileSystemException
+    {
+        WebdavFileObject file = (WebdavFileObject) (FileObjectUtils
+            .getAbstractFileObject(fileContent.getFile()));
+
+        String contentType = null;
+        String contentEncoding = null;
+
+        DavPropertyNameSet nameSet = new DavPropertyNameSet();
+        nameSet.add(DavPropertyName.GETCONTENTTYPE);
+        DavPropertySet propertySet = file.getProperties((URLFileName) file.getName(), nameSet, true);
+
+        DavProperty property = propertySet.get(DavPropertyName.GETCONTENTTYPE);
+        if (property != null)
+        {
+            contentType = (String) property.getValue();
+        }
+        property = propertySet.get(WebdavFileObject.RESPONSE_CHARSET);
+        if (property != null)
+        {
+            contentEncoding = (String) property.getValue();
+        }
+
+        return new DefaultFileContentInfo(contentType, contentEncoding);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileNameParser.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileNameParser.java
new file mode 100644
index 0000000..d9474d2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileNameParser.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.http.HttpFileNameParser;
+
+/**
+ * Implementation for http. set default port to 80
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class WebdavFileNameParser extends HttpFileNameParser
+{
+    private static final WebdavFileNameParser INSTANCE = new WebdavFileNameParser();
+
+    public WebdavFileNameParser()
+    {
+        super();
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileObject.java
new file mode 100644
index 0000000..ce7ed81
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileObject.java
@@ -0,0 +1,774 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.httpclient.HttpMethodBase;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.URIException;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
+import org.apache.commons.httpclient.util.DateUtil;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.provider.DefaultFileContent;
+import org.apache.commons.vfs.provider.http.HttpFileObject;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.commons.vfs.util.MonitorOutputStream;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.FileNotFolderException;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileNotFoundException;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.jackrabbit.webdav.client.methods.DavMethod;
+import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
+import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
+import org.apache.jackrabbit.webdav.client.methods.DeleteMethod;
+import org.apache.jackrabbit.webdav.client.methods.MoveMethod;
+import org.apache.jackrabbit.webdav.client.methods.PutMethod;
+import org.apache.jackrabbit.webdav.client.methods.CheckoutMethod;
+import org.apache.jackrabbit.webdav.client.methods.CheckinMethod;
+import org.apache.jackrabbit.webdav.client.methods.UncheckoutMethod;
+import org.apache.jackrabbit.webdav.client.methods.VersionControlMethod;
+import org.apache.jackrabbit.webdav.client.methods.PropPatchMethod;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.VersionControlledResource;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.apache.jackrabbit.webdav.property.DavPropertySet;
+import org.apache.jackrabbit.webdav.property.DavProperty;
+import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
+import org.w3c.dom.Node;
+
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Iterator;
+
+/**
+ * A WebDAV file.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$
+ */
+public class WebdavFileObject extends HttpFileObject implements FileObject
+{
+    /** The character set property name. */
+    public static final DavPropertyName RESPONSE_CHARSET = DavPropertyName.create(
+            "response-charset");
+
+    private final WebdavFileSystem fileSystem;
+    private final String urlCharset;
+
+    /** The FileSystemConfigBuilder */
+    private final WebdavFileSystemConfigBuilder builder;
+
+    protected WebdavFileObject(final FileName name, final WebdavFileSystem fileSystem)
+    {
+        super(name, fileSystem);
+        this.fileSystem = fileSystem;
+        builder = (WebdavFileSystemConfigBuilder) WebdavFileSystemConfigBuilder.getInstance();
+        this.urlCharset = builder.getUrlCharset(getFileSystem().getFileSystemOptions());
+    }
+
+    protected void configureMethod(HttpMethodBase httpMethod)
+    {
+        httpMethod.setMethodRetryHandler(WebdavMethodRetryHandler.getInstance());
+    }
+
+    /**
+     * Determines the type of this file.  Must not return null.  The return
+     * value of this method is cached, so the implementation can be expensive.
+     */
+    protected FileType doGetType() throws Exception
+    {
+        try
+        {
+            return isDirectory((URLFileName) getName()) ? FileType.FOLDER : FileType.FILE;
+        }
+        catch (FileNotFolderException fnfe)
+        {
+            return FileType.IMAGINARY;
+        }
+        catch (FileNotFoundException fnfe)
+        {
+            return FileType.IMAGINARY;
+        }
+
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        // use doListChildrenResolved for performance
+        return null;
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected FileObject[] doListChildrenResolved() throws Exception
+    {
+        PropFindMethod method = null;
+        try
+        {
+            URLFileName name = (URLFileName) getName();
+            if (isDirectory(name))
+            {
+                DavPropertyNameSet nameSet = new DavPropertyNameSet();
+                nameSet.add(DavPropertyName.create(DavConstants.PROPERTY_DISPLAYNAME));
+
+                method = new PropFindMethod(urlString(name), nameSet,
+                        DavConstants.DEPTH_1);
+
+                execute(method);
+                List vfs = new ArrayList();
+                if (method.succeeded())
+                {
+                    MultiStatusResponse[] responses =
+                            method.getResponseBodyAsMultiStatus().getResponses();
+
+                    for (int i = 0; i < responses.length; ++i)
+                    {
+                        MultiStatusResponse response = responses[i];
+                        if (isCurrentFile(response.getHref(), name))
+                        {
+                            continue;
+                        }
+                        String resourceName = resourceName(response.getHref());
+                        if (resourceName != null && resourceName.length() > 0)
+                        {
+                            WebdavFileObject fo = (WebdavFileObject) FileObjectUtils.
+                                    getAbstractFileObject(getFileSystem().resolveFile(
+                                            getFileSystem().getFileSystemManager().
+                                                    resolveName(getName(), resourceName,
+                                                    NameScope.CHILD)));
+                            vfs.add(fo);
+                        }
+                    }
+                }
+                return (WebdavFileObject[]) vfs.toArray(new WebdavFileObject[vfs.size()]);
+            }
+            throw new FileNotFolderException(getName());
+        }
+        catch (FileNotFolderException fnfe)
+        {
+            throw fnfe;
+        }
+        catch (DavException e)
+        {
+            throw new FileSystemException(e.getMessage(), e);
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e.getMessage(), e);
+        }
+        finally
+        {
+            if (method != null)
+            {
+                method.releaseConnection();
+            }
+        }
+    }
+
+    /**
+     * Creates this file as a folder.
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        DavMethod method = new MkColMethod(urlString((URLFileName) getName()));
+        setupMethod(method);
+        try
+        {
+            execute(method);
+        }
+        catch (FileSystemException fse)
+        {
+            throw new FileSystemException("vfs.provider.webdav/create-collection.error", getName(),
+                    fse);
+        }
+    }
+
+    /**
+     * Deletes the file.
+     */
+    protected void doDelete() throws Exception
+    {
+        DavMethod method = new DeleteMethod(urlString((URLFileName) getName()));
+        setupMethod(method);
+        execute(method);
+    }
+
+    /**
+     * Rename the file.
+     */
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        String url = encodePath(urlString((URLFileName) getName()));
+        String dest = urlString((URLFileName) newfile.getName(), false);
+        DavMethod method = new MoveMethod(url, dest, false);
+        setupMethod(method);
+        execute(method);
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        DavProperty property = getProperty((URLFileName) getName(),
+                DavConstants.PROPERTY_GETCONTENTLENGTH);
+        if (property != null)
+        {
+            String value = (String) property.getValue();
+            return Long.parseLong(value);
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the last modified time of this file.  Is only called if
+     * {@link #doGetType} does not return {@link FileType#IMAGINARY}.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        DavProperty property = getProperty((URLFileName) getName(),
+                DavConstants.PROPERTY_GETLASTMODIFIED);
+        if (property != null)
+        {
+            String value = (String) property.getValue();
+            return DateUtil.parseDate(value).getTime();
+        }
+        return 0;
+    }
+
+    /**
+     * Returns the properties of the Webdav resource.
+     */
+    protected Map doGetAttributes() throws Exception
+    {
+        final Map attributes = new HashMap();
+        try
+        {
+            URLFileName fileName = (URLFileName) getName();
+            DavPropertySet properties = getProperties(fileName, PropFindMethod.PROPFIND_ALL_PROP,
+                    new DavPropertyNameSet(), false);
+            Iterator iter = properties.iterator();
+            while (iter.hasNext())
+            {
+                DavProperty property = (DavProperty) iter.next();
+                attributes.put(property.getName().toString(), property.getValue());
+            }
+            properties = getPropertyNames(fileName);
+            iter = properties.iterator();
+            while (iter.hasNext())
+            {
+                DavProperty property = (DavProperty) iter.next();
+                if (!attributes.containsKey(property.getName()))
+                {
+                    property = getProperty(fileName, property.getName());
+                    if (property != null)
+                    {
+                        Object name = property.getName();
+                        Object value = property.getValue();
+                        if (name != null && value != null)
+                        {
+                            attributes.put(name.toString(), value);
+                        }
+                    }
+                }
+            }
+            return attributes;
+        }
+        catch (Exception e)
+        {
+            throw new FileSystemException("vfs.provider.webdav/propfind.error", getName(), e);
+        }
+    }
+
+    /**
+     * Sets an attribute of this file.  Is only called if {@link #doGetType}
+     * does not return {@link FileType#IMAGINARY}.
+     * <p/>
+     * This implementation throws an exception.
+     */
+    protected void doSetAttribute(final String attrName, final Object value)
+        throws Exception
+    {
+        try
+        {
+            URLFileName fileName = (URLFileName) getName();
+            String urlStr = urlString(fileName);
+            DavPropertySet properties = new DavPropertySet();
+            DavPropertyNameSet propertyNameSet = new DavPropertyNameSet();
+            DavProperty property = new DefaultDavProperty(attrName, value, Namespace.EMPTY_NAMESPACE);
+            if (value != null)
+            {
+                properties.add(property);
+            }
+            else
+            {
+                propertyNameSet.add(property.getName()); // remove property
+            }
+
+            PropPatchMethod method = new PropPatchMethod(urlStr, properties, propertyNameSet);
+            setupMethod(method);
+            execute(method);
+            if (!method.succeeded())
+            {
+                throw new FileSystemException("Property '" + attrName + "' could not be set.");
+            }
+        }
+        catch (FileSystemException fse)
+        {
+            throw fse;
+        }
+        catch (Exception e)
+        {
+            throw new FileSystemException("vfs.provider.webdav/propfind.error", getName(), e);
+        }
+    }
+
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        return new WebdavOutputStream(this);
+    }
+
+    protected FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return new WebdavFileContentInfoFactory();
+    }
+
+    /**
+     * Prepares a Method object.
+     *
+     * @param method the HttpMethod.
+     * @throws FileSystemException if an error occurs encoding the uri.
+     * @throws URIException        if the URI is in error.
+     */
+    protected void setupMethod(final HttpMethod method) throws FileSystemException, URIException
+    {
+        String pathEncoded = ((URLFileName) getName()).getPathQueryEncoded(urlCharset);
+        method.setPath(pathEncoded);
+        // All the WebDav methods are EntityEnclosingMethods and are not allowed to redirect.
+        method.setFollowRedirects(false);
+        method.setRequestHeader("User-Agent", "Jakarta-Commons-VFS");
+        method.addRequestHeader("Cache-control", "no-cache");
+        method.addRequestHeader("Cache-store", "no-store");
+        method.addRequestHeader("Pragma", "no-cache");
+        method.addRequestHeader("Expires", "0");
+    }
+
+    /**
+     * Execute a 'Workspace' operation.
+     *
+     * @param method The DavMethod to invoke.
+     * @throws FileSystemException If an error occurs.
+     */
+    private void execute(DavMethod method) throws FileSystemException
+    {
+        try
+        {
+            int status = fileSystem.getClient().executeMethod(method);
+            if (status == HttpURLConnection.HTTP_NOT_FOUND
+                    || status == HttpURLConnection.HTTP_GONE)
+            {
+                throw new FileNotFoundException(method.getURI());
+            }
+            method.checkSuccess();
+        }
+        catch (FileSystemException fse)
+        {
+            throw fse;
+        }
+        catch (IOException e)
+        {
+            throw new FileSystemException(e);
+        }
+        catch (DavException e)
+        {
+            throw ExceptionConverter.generate(e);
+        }
+        finally
+        {
+            if (method != null)
+            {
+                method.releaseConnection();
+            }
+        }
+    }
+
+    private boolean isDirectory(URLFileName name) throws IOException, DavException
+    {
+        try
+        {
+            DavProperty property = getProperty(name, DavConstants.PROPERTY_RESOURCETYPE);
+            Node node;
+            if (property != null && (node = (Node) property.getValue()) != null)
+            {
+                return node.getLocalName().equals(DavConstants.XML_COLLECTION);
+            }
+            else
+            {
+                return false;
+            }
+        }
+        catch (FileNotFoundException fse)
+        {
+            throw new FileNotFolderException(name);
+        }
+    }
+
+    DavProperty getProperty(URLFileName fileName, String property)
+            throws FileSystemException
+    {
+        return getProperty(fileName, DavPropertyName.create(property));
+    }
+
+    DavProperty getProperty(URLFileName fileName, DavPropertyName name)
+            throws FileSystemException
+    {
+        DavPropertyNameSet nameSet = new DavPropertyNameSet();
+        nameSet.add(name);
+        DavPropertySet propertySet = getProperties(fileName, nameSet, false);
+        return propertySet.get(name);
+    }
+
+    DavPropertySet getProperties(URLFileName name, DavPropertyNameSet nameSet, boolean addEncoding)
+            throws FileSystemException
+    {
+        return getProperties(name, PropFindMethod.PROPFIND_BY_PROPERTY, nameSet, addEncoding);
+    }
+
+    DavPropertySet getProperties(URLFileName name) throws FileSystemException
+    {
+        return getProperties(name, PropFindMethod.PROPFIND_ALL_PROP, new DavPropertyNameSet(),
+                false);
+    }
+
+
+    DavPropertySet getPropertyNames(URLFileName name) throws FileSystemException
+    {
+        return getProperties(name, PropFindMethod.PROPFIND_PROPERTY_NAMES,
+                new DavPropertyNameSet(), false);
+    }
+
+    DavPropertySet getProperties(URLFileName name, int type, DavPropertyNameSet nameSet,
+                                 boolean addEncoding)
+            throws FileSystemException
+    {
+        try
+        {
+            String urlStr = urlString(name);
+            PropFindMethod method = new PropFindMethod(urlStr, type, nameSet, DavConstants.DEPTH_0);
+            setupMethod(method);
+            execute(method);
+            if (method.succeeded())
+            {
+                MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
+                MultiStatusResponse response = multiStatus.getResponses()[0];
+                DavPropertySet props = response.getProperties(HttpStatus.SC_OK);
+                if (addEncoding)
+                {
+                    DavProperty prop = new DefaultDavProperty(RESPONSE_CHARSET,
+                            method.getResponseCharSet());
+                    props.add(prop);
+                }
+                return props;
+            }
+            return new DavPropertySet();
+        }
+        catch (FileSystemException fse)
+        {
+            throw fse;
+        }
+        catch (Exception e)
+        {
+            throw new FileSystemException("vfs.provider.webdav/propfind.error", getName(), e);
+        }
+    }
+
+    /**
+     * Returns the resource name from the path.
+     *
+     * @param path the path to the file.
+     * @return The resource name
+     */
+    private String resourceName(String path)
+    {
+        if (path.endsWith("/"))
+        {
+            path = path.substring(0, path.length() - 1);
+        }
+        final int i = path.lastIndexOf("/");
+        return (i >= 0) ? path.substring(i + 1) : path;
+    }
+
+    private String urlString(URLFileName name)
+    {
+        return urlString(name, true);
+    }
+
+    /**
+     * Convert the FileName to an encoded url String.
+     *
+     * @param name The FileName.
+     * @param includeUserInfo true if user information should be included.
+     * @return The encoded URL String.
+     */
+    private String urlString(URLFileName name, boolean includeUserInfo)
+    {
+        String user = null;
+        String password = null;
+        if (includeUserInfo)
+        {
+            user = name.getUserName();
+            password = name.getPassword();
+        }
+        URLFileName newFile = new URLFileName("http", name.getHostName(), name.getPort(),
+                name.getDefaultPort(), user, password,
+                name.getPath(), name.getType(), name.getQueryString());
+        try
+        {
+            return newFile.getURIEncoded(urlCharset);
+        }
+        catch (Exception e)
+        {
+            return name.getURI();
+        }
+    }
+
+    private boolean isCurrentFile(String href, URLFileName fileName)
+    {
+        String name = hrefString(fileName);
+        if (href.endsWith("/") && !name.endsWith("/"))
+        {
+            name += "/";
+        }
+        return href.equals(name);
+    }
+
+    /**
+     * Convert the FileName to an encoded url String.
+     *
+     * @param name The FileName.
+     * @return The encoded URL String.
+     */
+    private String hrefString(URLFileName name)
+    {
+        URLFileName newFile = new URLFileName("http", name.getHostName(), name.getPort(),
+                name.getDefaultPort(), null, null,
+                name.getPath(), name.getType(), name.getQueryString());
+        try
+        {
+            return newFile.getURIEncoded(urlCharset);
+        }
+        catch (Exception e)
+        {
+            return name.getURI();
+        }
+    }
+
+    /**
+     * An OutputStream that writes to a Webdav resource.
+     *
+     * @todo Use piped stream to avoid temporary file
+     */
+    private class WebdavOutputStream extends MonitorOutputStream
+    {
+        private WebdavFileObject file;
+
+        public WebdavOutputStream(WebdavFileObject file) throws FileSystemException
+        {
+            super(new ByteArrayOutputStream());
+            this.file = file;
+        }
+
+        /**
+         * Called after this stream is closed.
+         */
+        protected void onClose() throws IOException
+        {
+            RequestEntity entity = new ByteArrayRequestEntity(((ByteArrayOutputStream) out).toByteArray());
+            URLFileName fileName = (URLFileName) getName();
+            String urlStr = urlString(fileName);
+            if (builder.isVersioning(getFileSystem().getFileSystemOptions()))
+            {
+                DavPropertySet set = null;
+                boolean fileExists = true;
+                boolean isCheckedIn = true;
+                try
+                {
+                    set = getPropertyNames(fileName);
+                }
+                catch (FileNotFoundException fnfe)
+                {
+                    fileExists = false;
+                }
+                if (fileExists && set != null)
+                {
+                    if (set.contains(VersionControlledResource.CHECKED_OUT))
+                    {
+                        isCheckedIn = false;
+                    }
+                    else if (!set.contains(VersionControlledResource.CHECKED_IN))
+                    {
+                        DavProperty prop = set.get(VersionControlledResource.AUTO_VERSION);
+                        if (prop != null)
+                        {
+                            prop = getProperty(fileName, VersionControlledResource.AUTO_VERSION);
+                            if (DeltaVConstants.XML_CHECKOUT_CHECKIN.equals(prop.getValue()))
+                            {
+                                createVersion(urlStr);
+                            }
+                        }
+                    }
+                }
+                if (fileExists && isCheckedIn)
+                {
+                    try
+                    {
+                        CheckoutMethod checkout = new CheckoutMethod(urlStr);
+                        setupMethod(checkout);
+                        execute(checkout);
+                        isCheckedIn = false;
+                    }
+                    catch (FileSystemException ex)
+                    {
+                        // Ignore the exception checking out.
+                    }
+                }
+
+                try
+                {
+                    PutMethod method = new PutMethod(urlStr);
+                    method.setRequestEntity(entity);
+                    setupMethod(method);
+                    execute(method);
+                    setUserName(fileName, urlStr);
+                }
+                catch (FileSystemException ex)
+                {
+                    if (!isCheckedIn)
+                    {
+                        try
+                        {
+                            UncheckoutMethod method = new UncheckoutMethod(urlStr);
+                            setupMethod(method);
+                            execute(method);
+                            isCheckedIn = true;
+                        }
+                        catch (Exception e)
+                        {
+                            // Ignore the exception. Going to throw original.
+                        }
+                        throw ex;
+                    }
+                }
+                if (!fileExists)
+                {
+                    createVersion(urlStr);
+                    try
+                    {
+                        DavPropertySet props = getPropertyNames(fileName);
+                        isCheckedIn = !props.contains(VersionControlledResource.CHECKED_OUT);
+                    }
+                    catch (FileNotFoundException fnfe)
+                    {
+                        // Ignore the error
+                    }
+                }
+                if (!isCheckedIn)
+                {
+                  CheckinMethod checkin = new CheckinMethod(urlStr);
+                  setupMethod(checkin);
+                  execute(checkin);
+                }
+            }
+            else
+            {
+                PutMethod method = new PutMethod(urlStr);
+                method.setRequestEntity(entity);
+                setupMethod(method);
+                execute(method);
+                try
+                {
+                    setUserName(fileName, urlStr);
+                }
+                catch (IOException e)
+                {
+                    // Ignore the exception if unable to set the user name.
+                }
+            }
+            ((DefaultFileContent) this.file.getContent()).resetAttributes();
+        }
+
+        private void setUserName(URLFileName fileName, String urlStr)
+                throws IOException
+        {
+            List list = new ArrayList();
+            String name = builder.getCreatorName(getFileSystem().getFileSystemOptions());
+            String userName = fileName.getUserName();
+            if (name == null)
+            {
+                name = userName;
+            }
+            else
+            {
+                if (userName != null)
+                {
+                    String comment = "Modified by user " + userName;
+                    list.add(new DefaultDavProperty(DeltaVConstants.COMMENT, comment));
+                }
+            }
+            list.add(new DefaultDavProperty(DeltaVConstants.CREATOR_DISPLAYNAME, name));
+            PropPatchMethod method = new PropPatchMethod(urlStr, list);
+            setupMethod(method);
+            execute(method);
+        }
+
+        private boolean createVersion(String urlStr)
+        {
+            try
+            {
+                VersionControlMethod method = new VersionControlMethod(urlStr);
+                setupMethod(method);
+                execute(method);
+                return true;
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileProvider.java
new file mode 100644
index 0000000..4d51191
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileProvider.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+import org.apache.commons.vfs.provider.GenericFileName;
+import org.apache.commons.vfs.provider.http.HttpFileProvider;
+import org.apache.commons.vfs.provider.http.HttpClientFactory;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A provider for WebDAV.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$ $Date$
+ */
+public class WebdavFileProvider
+    extends HttpFileProvider
+{
+    /** The authenticator types used by the WebDAV provider. */
+    public static final UserAuthenticationData.Type[] AUTHENTICATOR_TYPES = new UserAuthenticationData.Type[]
+        {
+            UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD
+        };
+
+    /** The capabilities of the WebDAV provider */
+    protected static final Collection capabilities =
+            Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.CREATE,
+        Capability.DELETE,
+        Capability.RENAME,
+        Capability.GET_TYPE,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.WRITE_CONTENT,
+        Capability.GET_LAST_MODIFIED,
+        Capability.ATTRIBUTES,
+        Capability.RANDOM_ACCESS_READ,
+        Capability.DIRECTORY_READ_CONTENT,
+    }));
+
+    public WebdavFileProvider()
+    {
+        super();
+
+        setFileNameParser(WebdavFileNameParser.getInstance());
+    }
+    /**
+     * Creates a {@link FileSystem}.  If you're looking at this method and wondering how to 
+     * get a FileSystemOptions object bearing the proxy host and credentials configuration through 
+     * to this method so it's used for resolving a {@link FileObject} in the FileSystem, then be sure
+     * to use correct signature of the {@link FileSystemManager} resolveFile method.
+     * @see org.apache.commons.vfs.impl.DefaultFileSystemManager.resolveFile(FileObject, String, FileSystemOptions).
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        // Create the file system
+        final GenericFileName rootName = (GenericFileName) name;
+        FileSystemOptions fsOpts = (fileSystemOptions == null) ? new FileSystemOptions() : fileSystemOptions;
+
+        UserAuthenticationData authData = null;
+        HttpClient httpClient;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(fsOpts, AUTHENTICATOR_TYPES);
+
+            httpClient = HttpClientFactory.createConnection(
+                WebdavFileSystemConfigBuilder.getInstance(),
+                "http",
+                rootName.getHostName(),
+                rootName.getPort(),
+                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                        UserAuthenticationData.USERNAME, UserAuthenticatorUtils.toChar(rootName.getUserName()))),
+                UserAuthenticatorUtils.toString(UserAuthenticatorUtils.getData(authData,
+                        UserAuthenticationData.PASSWORD, UserAuthenticatorUtils.toChar(rootName.getPassword()))),
+                fsOpts);
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+
+        return new WebdavFileSystem(rootName, httpClient, fsOpts);
+    }
+
+    public FileSystemConfigBuilder getConfigBuilder()
+    {
+        return WebdavFileSystemConfigBuilder.getInstance();
+    }
+
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystem.java
new file mode 100644
index 0000000..c58fe10
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystem.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import java.net.URLStreamHandler;
+import java.util.Collection;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.DefaultURLStreamHandler;
+import org.apache.commons.vfs.provider.GenericFileName;
+import org.apache.commons.vfs.provider.http.HttpFileSystem;
+
+/**
+ * A WebDAV file system.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$ $Date$
+ */
+public class WebdavFileSystem extends HttpFileSystem implements FileSystem
+{
+    protected WebdavFileSystem(final GenericFileName rootName, final HttpClient client,
+                               final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, client, fileSystemOptions);
+    }
+
+    protected HttpClient getClient()
+    {
+        return super.getClient();
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     * @caps The Capabilities to add.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(WebdavFileProvider.capabilities);
+    }
+
+    /**
+     * Creates a file object.  This method is called only if the requested
+     * file is not cached.
+     * @param name the FileName.
+     * @return The created FileObject.
+     */
+    protected FileObject createFile(final FileName name)
+    {
+
+        return new WebdavFileObject(name, this);
+    }
+
+    /**
+     * Return a URLStreamHandler.
+     * @return The URLStreamHandler.
+     */
+    public URLStreamHandler getURLStreamHandler()
+    {
+        return new DefaultURLStreamHandler(getContext(), getFileSystemOptions());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystemConfigBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystemConfigBuilder.java
new file mode 100644
index 0000000..94c9919
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavFileSystemConfigBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
+
+/**
+ * Configuration options for WebDav.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$ $Date$
+ */
+public final class WebdavFileSystemConfigBuilder extends HttpFileSystemConfigBuilder
+{
+    private static final WebdavFileSystemConfigBuilder BUILDER = new WebdavFileSystemConfigBuilder();
+
+    private WebdavFileSystemConfigBuilder()
+    {
+        super("webdav.");
+    }
+
+    public static HttpFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * 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.
+     */
+    public void setCreatorName(FileSystemOptions opts, String creatorName)
+    {
+        setParam(opts, "creatorName", creatorName);
+    }
+
+    /**
+     * Return the user name to be associated with changes to the file.
+     * @param opts The FileSystem options
+     * @return The creatorName.
+     */
+    public String getCreatorName(FileSystemOptions opts)
+    {
+        return getString(opts, "creatorName");
+    }
+
+    /**
+     * Whether to use versioning.
+     * @param opts The FileSystem options.
+     * @param versioning true if versioning should be enabled.
+     */
+    public void setVersioning(FileSystemOptions opts, boolean versioning)
+    {
+        setParam(opts, "versioning", Boolean.valueOf(versioning));
+    }
+
+    /**
+     * The cookies to add to the request.
+     * @param opts The FileSystem options.
+     * @return true if versioning is enabled.
+     */
+    public boolean isVersioning(FileSystemOptions opts)
+    {
+        return getBoolean(opts, "versioning", false);
+    }
+
+    /**
+     * @return The Webdav FileSystem Class object.
+     */
+    protected Class getConfigClass()
+    {
+        return WebdavFileSystem.class;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavMethodRetryHandler.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavMethodRetryHandler.java
new file mode 100644
index 0000000..47d1b1a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/WebdavMethodRetryHandler.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav;
+
+import org.apache.commons.httpclient.MethodRetryHandler;
+import org.apache.commons.httpclient.HttpMethod;
+import org.apache.commons.httpclient.HttpConnection;
+import org.apache.commons.httpclient.HttpRecoverableException;
+
+
+/**
+ * A retry handler which will retry a failed webdav method one time.<br />
+ * Now that webdavlib didnt support adding a MethodRetryHandler only a few operations are restartable yet.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Revision$ $Date$
+ */
+public final class WebdavMethodRetryHandler implements MethodRetryHandler
+{
+    private static final WebdavMethodRetryHandler INSTANCE = new WebdavMethodRetryHandler();
+
+    private WebdavMethodRetryHandler()
+    {
+    }
+
+    public static WebdavMethodRetryHandler getInstance()
+    {
+        return INSTANCE;
+    }
+
+    public boolean retryMethod(HttpMethod method, HttpConnection connection,
+                               HttpRecoverableException recoverableException, int executionCount,
+                               boolean requestSent)
+    {
+        return executionCount < 2;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/package.html
new file mode 100644
index 0000000..b02dd8d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/webdav/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The WebDAV File Provider</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileObject.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileObject.java
new file mode 100644
index 0000000..d64f50c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileObject.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.zip;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.zip.ZipEntry;
+
+/**
+ * A file in a Zip file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class ZipFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    /** The ZipEntry. */
+    protected ZipEntry entry;
+    private final HashSet children = new HashSet();
+    private final ZipFileSystem fs;
+    // protected final ZipFile file;
+
+    private FileType type;
+
+    protected ZipFileObject(FileName name,
+                            ZipEntry entry,
+                            ZipFileSystem fs,
+                            boolean zipExists) throws FileSystemException
+    {
+        super(name, fs);
+        this.fs = fs;
+        setZipEntry(entry);
+        if (!zipExists)
+        {
+            type = FileType.IMAGINARY;
+        }
+    }
+
+    /**
+     * Sets the details for this file object.
+     */
+    protected void setZipEntry(final ZipEntry entry)
+    {
+        if (this.entry != null)
+        {
+            return;
+        }
+
+        if ((entry == null) || (entry.isDirectory()))
+        {
+            type = FileType.FOLDER;
+        }
+        else
+        {
+            type = FileType.FILE;
+        }
+
+        this.entry = entry;
+    }
+
+    /**
+     * Attaches a child.
+     * @param childName The name of the child.
+     */
+    public void attachChild(FileName childName)
+    {
+        children.add(childName.getBaseName());
+    }
+
+    /**
+     * Determines if this file can be written to.
+     *
+     * @return <code>true</code> if this file is writeable, <code>false</code> if not.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean isWriteable() throws FileSystemException
+    {
+        return false;
+    }
+
+    /**
+     * Returns the file's type.
+     */
+    protected FileType doGetType()
+    {
+        return type;
+    }
+
+    /**
+     * Lists the children of the file.
+     */
+    protected String[] doListChildren()
+    {
+        try
+        {
+            if (!getType().hasChildren())
+            {
+                return null;
+            }
+        }
+        catch (FileSystemException e)
+        {
+            // should not happen as the type has already been cached.
+            throw new RuntimeException(e);
+        }
+
+        return (String[]) children.toArray(new String[children.size()]);
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).  Is only called if
+     * {@link #doGetType} returns {@link FileType#FILE}.
+     */
+    protected long doGetContentSize()
+    {
+        return entry.getSize();
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime() throws Exception
+    {
+        return entry.getTime();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.  Is only called
+     * if  {@link #doGetType} returns {@link FileType#FILE}.  The input stream
+     * returned by this method is guaranteed to be closed before this
+     * method is called again.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        // VFS-210: zip allows to gather an input stream even from a directory and will
+        // return -1 on the first read. getType should not be expensive and keeps the tests
+        // running
+        if (!getType().hasContent())
+        {
+            throw new FileSystemException("vfs.provider/read-not-file.error", getName());
+        }
+
+        return fs.getZipFile().getInputStream(entry);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileProvider.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileProvider.java
new file mode 100644
index 0000000..80be103
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileProvider.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.zip;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractLayeredFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.LayeredFileName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A file system provider for Zip files.  Provides read-only file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class ZipFileProvider
+    extends AbstractLayeredFileProvider
+    implements FileProvider
+{
+    /** The list of capabilities this provider supports */
+    protected static final Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+        {
+            Capability.GET_LAST_MODIFIED,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT,
+            Capability.URI,
+            Capability.COMPRESS,
+            Capability.VIRTUAL
+        }));
+
+    public ZipFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Creates a layered file system.  This method is called if the file system
+     * is not cached.
+     *
+     * @param scheme The URI scheme.
+     * @param file   The file to create the file system on top of.
+     * @return The file system.
+     */
+    protected FileSystem doCreateFileSystem(final String scheme,
+                                            final FileObject file,
+                                            final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        final FileName rootName =
+            new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
+        return new ZipFileSystem(rootName, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileSystem.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileSystem.java
new file mode 100644
index 0000000..c2ddd26
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/ZipFileSystem.java
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.zip;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.UriParser;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * A read-only file system for Zip/Jar files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class ZipFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    private static final Log LOG = LogFactory.getLog(ZipFileSystem.class);
+
+    private final File file;
+    private ZipFile zipFile;
+
+  public ZipFileSystem(final FileName rootName,
+                         final FileObject parentLayer,
+                         final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+
+        // Make a local copy of the file
+        file = parentLayer.getFileSystem().replicateFile(parentLayer, Selectors.SELECT_SELF);
+
+        // Open the Zip file
+        if (!file.exists())
+        {
+            // Don't need to do anything
+            zipFile = null;
+            return;
+        }
+
+        // zipFile = createZipFile(this.file);
+    }
+
+    public void init() throws FileSystemException
+    {
+        super.init();
+
+        try
+        {
+            // Build the index
+            List strongRef = new ArrayList(100);
+            Enumeration entries = getZipFile().entries();
+            while (entries.hasMoreElements())
+            {
+                ZipEntry entry = (ZipEntry) entries.nextElement();
+                FileName name = getFileSystemManager().resolveName(getRootName(), UriParser.encode(entry.getName()));
+
+                // Create the file
+                ZipFileObject fileObj;
+                if (entry.isDirectory() && getFileFromCache(name) != null)
+                {
+                    fileObj = (ZipFileObject) getFileFromCache(name);
+                    fileObj.setZipEntry(entry);
+                    continue;
+                }
+
+                fileObj = createZipFileObject(name, entry);
+                putFileToCache(fileObj);
+                strongRef.add(fileObj);
+                fileObj.holdObject(strongRef);
+
+                // Make sure all ancestors exist
+                // TODO - create these on demand
+                ZipFileObject parent;
+                for (FileName parentName = name.getParent();
+                     parentName != null;
+                     fileObj = parent, parentName = parentName.getParent())
+                {
+                    // Locate the parent
+                    parent = (ZipFileObject) getFileFromCache(parentName);
+                    if (parent == null)
+                    {
+                        parent = createZipFileObject(parentName, null);
+                        putFileToCache(parent);
+                        strongRef.add(parent);
+                        parent.holdObject(strongRef);
+                    }
+
+                    // Attach child to parent
+                    parent.attachChild(fileObj.getName());
+                }
+            }
+        }
+        finally
+        {
+            closeCommunicationLink();
+        }
+    }
+
+    protected ZipFile getZipFile() throws FileSystemException
+    {
+        if (zipFile == null && this.file.exists())
+        {
+            ZipFile zipFile = createZipFile(this.file);
+
+            this.zipFile = zipFile;
+        }
+
+        return zipFile;
+    }
+
+    protected ZipFileObject createZipFileObject(final FileName name,
+                                                final ZipEntry entry) throws FileSystemException
+    {
+        return new ZipFileObject(name, entry, this, true);
+    }
+
+    protected ZipFile createZipFile(final File file) throws FileSystemException
+    {
+        try
+        {
+            return new ZipFile(file);
+        }
+        catch (IOException ioe)
+        {
+            throw new FileSystemException("vfs.provider.zip/open-zip-file.error", file, ioe);
+        }
+    }
+
+    protected void doCloseCommunicationLink()
+    {
+        // Release the zip file
+        try
+        {
+            if (zipFile != null)
+            {
+                zipFile.close();
+                zipFile = null;
+            }
+        }
+        catch (final IOException e)
+        {
+            // getLogger().warn("vfs.provider.zip/close-zip-file.error :" + file, e);
+            VfsLog.warn(getLogger(), LOG, "vfs.provider.zip/close-zip-file.error :" + file, e);
+        }
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(ZipFileProvider.capabilities);
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name) throws FileSystemException
+    {
+        // This is only called for files which do not exist in the Zip file
+        return new ZipFileObject(name, null, this, false);
+    }
+
+    /**
+     * will be called after all file-objects closed their streams.
+    protected void notifyAllStreamsClosed()
+    {
+        closeCommunicationLink();
+    }
+     */
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/package.html
new file mode 100644
index 0000000..b0126aa
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/provider/zip/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The Zip File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/AbstractSyncTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/AbstractSyncTask.java
new file mode 100644
index 0000000..00762b4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/AbstractSyncTask.java
@@ -0,0 +1,472 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.util.Messages;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * An abstract file synchronization task.  Scans a set of source files and
+ * folders, and a destination folder, and performs actions on missing and
+ * out-of-date files.  Specifically, performs actions on the following:
+ * <ul>
+ * <li>Missing destination file.
+ * <li>Missing source file.
+ * <li>Out-of-date destination file.
+ * <li>Up-to-date destination file.
+ * </ul>
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Deal with case where dest file maps to a child of one of the source files
+ * @todo Deal with case where dest file already exists and is incorrect type (not file, not a folder)
+ * @todo Use visitors
+ * @todo Add default excludes
+ * @todo Allow selector, mapper, filters, etc to be specified.
+ * @todo Handle source/dest directories as well
+ * @todo Allow selector to be specified for choosing which dest files to sync
+ */
+public abstract class AbstractSyncTask
+    extends VfsTask
+{
+    private final ArrayList srcFiles = new ArrayList();
+    private String destFileUrl;
+    private String destDirUrl;
+    private String srcDirUrl;
+    private boolean srcDirIsBase;
+    private boolean failonerror = true;
+    private String filesList;
+
+    /**
+     * Sets the destination file.
+     * @param destFile The destination file name.
+     */
+    public void setDestFile(final String destFile)
+    {
+        this.destFileUrl = destFile;
+    }
+
+    /**
+     * Sets the destination directory.
+     * @param destDir The destination directory.
+     */
+    public void setDestDir(final String destDir)
+    {
+        this.destDirUrl = destDir;
+    }
+
+    /**
+     * Sets the source file.
+     * @param srcFile The source file name.
+     */
+    public void setSrc(final String srcFile)
+    {
+        final SourceInfo src = new SourceInfo();
+        src.setFile(srcFile);
+        addConfiguredSrc(src);
+    }
+
+    /**
+     * Sets the source directory.
+     * @param srcDir The source directory.
+     */
+    public void setSrcDir(final String srcDir)
+    {
+        this.srcDirUrl = srcDir;
+    }
+
+    /**
+     * Sets whether the source directory should be consider as the base directory.
+     * @param srcDirIsBase true if the source directory is the base directory.
+     */
+    public void setSrcDirIsBase(final boolean srcDirIsBase)
+    {
+        this.srcDirIsBase = srcDirIsBase;
+    }
+
+    /**
+     * Sets whether we should fail if there was an error or not.
+     * @param failonerror true if the operation should fail if there is an error.
+     */
+    public void setFailonerror(final boolean failonerror)
+    {
+        this.failonerror = failonerror;
+    }
+
+    /**
+     * Sets whether we should fail if there was an error or not.
+     * @return true if the operation should fail if there was an error.
+     */
+    public boolean isFailonerror()
+    {
+        return failonerror;
+    }
+
+    /**
+     * Sets the files to includes.
+     * @param filesList The list of files to include.
+     */
+    public void setIncludes(final String filesList)
+    {
+        this.filesList = filesList;
+    }
+
+    /**
+     * Adds a nested &lt;src&gt; element.
+     * @param srcInfo A nested source element.
+     * @throws BuildException if the SourceInfo doesn't reference a file.
+     */
+    public void addConfiguredSrc(final SourceInfo srcInfo)
+        throws BuildException
+    {
+        if (srcInfo.file == null)
+        {
+            final String message = Messages.getString("vfs.tasks/sync.no-source-file.error");
+            throw new BuildException(message);
+        }
+        srcFiles.add(srcInfo);
+    }
+
+    /**
+     * Executes this task.
+     * @throws BuildException if an error occurs.
+     */
+    public void execute() throws BuildException
+    {
+        // Validate
+        if (destFileUrl == null && destDirUrl == null)
+        {
+            final String message =
+                Messages.getString("vfs.tasks/sync.no-destination.error");
+            logOrDie(message, Project.MSG_WARN);
+            return;
+        }
+
+        if (destFileUrl != null && destDirUrl != null)
+        {
+            final String message =
+                Messages.getString("vfs.tasks/sync.too-many-destinations.error");
+            logOrDie(message, Project.MSG_WARN);
+            return;
+        }
+
+        // Add the files of the includes attribute to the list
+        if (srcDirUrl != null && !srcDirUrl.equals(destDirUrl) && filesList != null && filesList.length() > 0)
+        {
+            if (!srcDirUrl.endsWith("/"))
+            {
+                srcDirUrl += "/";
+            }
+            StringTokenizer tok = new StringTokenizer(filesList, ", \t\n\r\f", false);
+            while (tok.hasMoreTokens())
+            {
+                String nextFile = tok.nextToken();
+
+                // Basic compatibility with Ant fileset for directories
+                if (nextFile.endsWith("/**"))
+                {
+                    nextFile = nextFile.substring(0, nextFile.length() - 2);
+                }
+
+                final SourceInfo src = new SourceInfo();
+                src.setFile(srcDirUrl + nextFile);
+                addConfiguredSrc(src);
+            }
+        }
+
+        if (srcFiles.size() == 0)
+        {
+            final String message = Messages.getString("vfs.tasks/sync.no-source-files.warn");
+            logOrDie(message, Project.MSG_WARN);
+            return;
+        }
+
+        // Perform the sync
+        try
+        {
+            if (destFileUrl != null)
+            {
+                handleSingleFile();
+            }
+            else
+            {
+                handleFiles();
+            }
+        }
+        catch (final BuildException e)
+        {
+            throw e;
+        }
+        catch (final Exception e)
+        {
+            throw new BuildException(e.getMessage(), e);
+        }
+    }
+
+    protected void logOrDie(final String message, int level)
+    {
+        if (!isFailonerror())
+        {
+            log(message, level);
+            return;
+        }
+        throw new BuildException(message);
+    }
+
+    /**
+     * Copies the source files to the destination.
+     */
+    private void handleFiles() throws Exception
+    {
+        // Locate the destination folder, and make sure it exists
+        final FileObject destFolder = resolveFile(destDirUrl);
+        destFolder.createFolder();
+
+        // Locate the source files, and make sure they exist
+        FileName srcDirName = null;
+        if (srcDirUrl != null)
+        {
+            srcDirName = resolveFile(srcDirUrl).getName();
+        }
+        final ArrayList srcs = new ArrayList();
+        for (int i = 0; i < srcFiles.size(); i++)
+        {
+            // Locate the source file, and make sure it exists
+            final SourceInfo src = (SourceInfo) srcFiles.get(i);
+            final FileObject srcFile = resolveFile(src.file);
+            if (!srcFile.exists())
+            {
+                final String message =
+                    Messages.getString("vfs.tasks/sync.src-file-no-exist.warn", srcFile);
+
+                logOrDie(message, Project.MSG_WARN);
+            }
+            else
+            {
+                srcs.add(srcFile);
+            }
+        }
+
+        // Scan the source files
+        final Set destFiles = new HashSet();
+        for (int i = 0; i < srcs.size(); i++)
+        {
+            final FileObject rootFile = (FileObject) srcs.get(i);
+            final FileName rootName = rootFile.getName();
+
+            if (rootFile.getType() == FileType.FILE)
+            {
+                // Build the destination file name
+                String relName = null;
+                if (srcDirName == null || !srcDirIsBase)
+                {
+                    relName = rootName.getBaseName();
+                }
+                else
+                {
+                    relName = srcDirName.getRelativeName(rootName);
+                }
+                final FileObject destFile = destFolder.resolveFile(relName, NameScope.DESCENDENT);
+
+                // Do the copy
+                handleFile(destFiles, rootFile, destFile);
+            }
+            else
+            {
+                // Find matching files
+                // If srcDirIsBase is true, select also the sub-directories
+                final FileObject[] files = rootFile.findFiles(srcDirIsBase
+                    ? Selectors.SELECT_ALL : Selectors.SELECT_FILES);
+
+                for (int j = 0; j < files.length; j++)
+                {
+                    final FileObject srcFile = files[j];
+
+                    // Build the destination file name
+                    String relName = null;
+                    if (srcDirName == null || !srcDirIsBase)
+                    {
+                        relName = rootName.getRelativeName(srcFile.getName());
+                    }
+                    else
+                    {
+                        relName = srcDirName.getRelativeName(srcFile.getName());
+                    }
+
+                    final FileObject destFile =
+                        destFolder.resolveFile(relName, NameScope.DESCENDENT);
+
+                    // Do the copy
+                    handleFile(destFiles, srcFile, destFile);
+                }
+            }
+        }
+
+        // Scan the destination files for files with no source file
+        if (detectMissingSourceFiles())
+        {
+            final FileObject[] allDestFiles = destFolder.findFiles(Selectors.SELECT_FILES);
+            for (int i = 0; i < allDestFiles.length; i++)
+            {
+                final FileObject destFile = allDestFiles[i];
+                if (!destFiles.contains(destFile))
+                {
+                    handleMissingSourceFile(destFile);
+                }
+            }
+        }
+    }
+
+    /**
+     * Handles a single file, checking for collisions where more than one
+     * source file maps to the same destination file.
+     */
+    private void handleFile(final Set destFiles,
+                            final FileObject srcFile,
+                            final FileObject destFile) throws Exception
+
+    {
+        // Check for duplicate source files
+        if (destFiles.contains(destFile))
+        {
+            final String message = Messages.getString("vfs.tasks/sync.duplicate-source-files.warn", destFile);
+            logOrDie(message, Project.MSG_WARN);
+        }
+        else
+        {
+            destFiles.add(destFile);
+        }
+
+        // Handle the file
+        handleFile(srcFile, destFile);
+    }
+
+    /**
+     * Copies a single file.
+     */
+    private void handleSingleFile() throws Exception
+    {
+        // Make sure there is exactly one source file, and that it exists
+        // and is a file.
+        if (srcFiles.size() > 1)
+        {
+            final String message =
+                Messages.getString("vfs.tasks/sync.too-many-source-files.error");
+            logOrDie(message, Project.MSG_WARN);
+            return;
+        }
+        final SourceInfo src = (SourceInfo) srcFiles.get(0);
+        final FileObject srcFile = resolveFile(src.file);
+        if (srcFile.getType() != FileType.FILE)
+        {
+            final String message =
+                Messages.getString("vfs.tasks/sync.source-not-file.error", srcFile);
+            logOrDie(message, Project.MSG_WARN);
+            return;
+        }
+
+        // Locate the destination file
+        final FileObject destFile = resolveFile(destFileUrl);
+
+        // Do the copy
+        handleFile(srcFile, destFile);
+    }
+
+    /**
+     * Handles a single source file.
+     */
+    private void handleFile(final FileObject srcFile,
+                            final FileObject destFile)
+        throws Exception
+    {
+        if (!destFile.exists()
+            || srcFile.getContent().getLastModifiedTime() > destFile.getContent().getLastModifiedTime())
+        {
+            // Destination file is out-of-date
+            handleOutOfDateFile(srcFile, destFile);
+        }
+        else
+        {
+            // Destination file is up-to-date
+            handleUpToDateFile(srcFile, destFile);
+        }
+    }
+
+    /**
+     * Handles an out-of-date file (a file where the destination file
+     * either doesn't exist, or is older than the source file).
+     * This implementation does nothing.
+     */
+    protected void handleOutOfDateFile(final FileObject srcFile,
+                                       final FileObject destFile)
+        throws Exception
+    {
+    }
+
+    /**
+     * Handles an up-to-date file (where the destination file exists and is
+     * newer than the source file).  This implementation does nothing.
+     */
+    protected void handleUpToDateFile(final FileObject srcFile,
+                                      final FileObject destFile)
+        throws Exception
+    {
+    }
+
+    /**
+     * Handles a destination for which there is no corresponding source file.
+     * This implementation does nothing.
+     */
+    protected void handleMissingSourceFile(final FileObject destFile)
+        throws Exception
+    {
+    }
+
+    /**
+     * Check if this task cares about destination files with a missing source
+     * file.  This implementation returns false.
+     */
+    protected boolean detectMissingSourceFiles()
+    {
+        return false;
+    }
+
+    /**
+     * Information about a source file.
+     */
+    public static class SourceInfo
+    {
+        private String file;
+
+        public void setFile(final String file)
+        {
+            this.file = file;
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/CopyTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/CopyTask.java
new file mode 100644
index 0000000..cbfde20
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/CopyTask.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.Selectors;
+
+/**
+ * An Ant task that copies matching files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Copy folders that do not contain files
+ */
+public class CopyTask
+    extends AbstractSyncTask
+{
+    private boolean overwrite;
+    private boolean preserveLastModified = true;
+
+    /**
+     * Enable/disable overwriting of up-to-date files.
+     * @param overwrite true if the file should be overwritten.
+     */
+    public void setOverwrite(boolean overwrite)
+    {
+        this.overwrite = overwrite;
+    }
+
+    /**
+     * Enable/disable preserving last modified time of copied files.
+     * @param preserveLastModified true if the last modified time should be preserved.
+     */
+    public void setPreserveLastModified(boolean preserveLastModified)
+    {
+        this.preserveLastModified = preserveLastModified;
+    }
+
+    /**
+     * @return the current value of overwrite
+     */
+    public boolean isOverwrite()
+    {
+        return overwrite;
+    }
+
+    /**
+     * @return the current value of preserveLastModified
+     */
+    public boolean isPreserveLastModified()
+    {
+        return preserveLastModified;
+    }
+
+    /**
+     * Handles an out-of-date file.
+     * @param srcFile The source FileObject.
+     * @param destFile The destination FileObject.
+     */
+    protected void handleOutOfDateFile(final FileObject srcFile,
+                                       final FileObject destFile)
+        throws FileSystemException
+    {
+        log("Copying " + srcFile + " to " + destFile);
+        destFile.copyFrom(srcFile, Selectors.SELECT_SELF);
+        if (preserveLastModified
+            && srcFile.getFileSystem().hasCapability(Capability.GET_LAST_MODIFIED)
+            && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE))
+        {
+            final long lastModTime = srcFile.getContent().getLastModifiedTime();
+            destFile.getContent().setLastModifiedTime(lastModTime);
+        }
+    }
+
+    /**
+     * Handles an up-to-date file.
+     * @param srcFile The source FileObject.
+     * @param destFile The destination FileObject.
+     */
+    protected void handleUpToDateFile(final FileObject srcFile,
+                                      final FileObject destFile)
+        throws FileSystemException
+    {
+        if (overwrite)
+        {
+            // Copy the file anyway
+            handleOutOfDateFile(srcFile, destFile);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/DeleteTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/DeleteTask.java
new file mode 100644
index 0000000..0b02724
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/DeleteTask.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.util.Messages;
+import org.apache.tools.ant.BuildException;
+
+import java.util.StringTokenizer;
+
+/**
+ * An Ant task that deletes matching files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Allow selector to be specified.
+ */
+public class DeleteTask
+    extends VfsTask
+{
+    private String file;
+    private String srcDirUrl;
+    private String filesList;
+
+    /**
+     * Sets the file/folder to delete.
+     *
+     * @param file The name of the file.
+     */
+    public void setFile(final String file)
+    {
+        this.file = file;
+    }
+
+    /**
+     * Sets the source directory.
+     * @param srcDir The source directory.
+     */
+    public void setSrcDir(final String srcDir)
+    {
+        this.srcDirUrl = srcDir;
+    }
+
+    /**
+     * Sets the files to include.
+     * @param filesList The list of files.
+     */
+    public void setIncludes(final String filesList)
+    {
+        this.filesList = filesList;
+    }
+
+    /**
+     * Executes this task.
+     * @throws BuildException if an error occurs.
+     */
+    public void execute() throws BuildException
+    {
+        if ((file == null && srcDirUrl == null) || (srcDirUrl != null && filesList == null))
+        {
+            final String message = Messages.getString("vfs.tasks/delete.no-source-files.error");
+            throw new BuildException(message);
+        }
+
+        try
+        {
+            if (srcDirUrl != null && filesList != null)
+            {
+                log("Deleting " + filesList + " in the directory " + srcDirUrl);
+                if (!srcDirUrl.endsWith("/"))
+                {
+                    srcDirUrl += "/";
+                }
+                StringTokenizer tok = new StringTokenizer(filesList, ", \t\n\r\f", false);
+                while (tok.hasMoreTokens())
+                {
+                    String nextFile = tok.nextToken();
+                    final FileObject srcFile = resolveFile(srcDirUrl + nextFile);
+                    srcFile.delete(Selectors.SELECT_ALL);
+                }
+            }
+            else
+            {
+                final FileObject srcFile = resolveFile(file);
+                log("Deleting " + srcFile);
+                srcFile.delete(Selectors.SELECT_ALL);
+            }
+        }
+        catch (final Exception e)
+        {
+            throw new BuildException(e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MkdirTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MkdirTask.java
new file mode 100644
index 0000000..f0fa25e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MkdirTask.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.util.Messages;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * An Ant task that creates a directory.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class MkdirTask
+    extends VfsTask
+{
+    private String dirName;
+
+    /**
+     * Sets the directory to create.
+     *
+     * @param dir The directory name.
+     */
+    public void setDir(final String dir)
+    {
+        dirName = dir;
+    }
+
+    /**
+     * Executes the task.
+     * @throws BuildException if an exception occurs.
+     */
+    public void execute() throws BuildException
+    {
+        if (dirName == null)
+        {
+            final String message = Messages.getString("vfs.tasks/no-directory-specified.error");
+            throw new BuildException(message);
+        }
+
+        try
+        {
+            final FileObject dir = resolveFile(dirName);
+            final String message = Messages.getString("vfs.tasks/mkdir.create-folder.info", dir);
+            log(message);
+            dir.createFolder();
+        }
+        catch (final FileSystemException e)
+        {
+            throw new BuildException(e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MoveTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MoveTask.java
new file mode 100644
index 0000000..8302736
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/MoveTask.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.Selectors;
+
+/**
+ * An Ant task that moves matching files.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Delete matching folders
+ */
+public class MoveTask
+    extends CopyTask
+{
+    private boolean tryRename;
+
+    /**
+     * Enable/disable move/rename of file (if possible).
+     * @param tryRename true if the file should be renamed.
+     */
+    public void setTryRename(boolean tryRename)
+    {
+        this.tryRename = tryRename;
+    }
+
+    /**
+     * Handles a single source file.
+     */
+    protected void handleOutOfDateFile(final FileObject srcFile,
+                                       final FileObject destFile)
+        throws FileSystemException
+    {
+        if (!tryRename || !srcFile.canRenameTo(destFile))
+        {
+            super.handleOutOfDateFile(srcFile, destFile);
+
+            log("Deleting " + srcFile);
+            srcFile.delete(Selectors.SELECT_SELF);
+        }
+        else
+        {
+            log("Rename " + srcFile + " to " + destFile);
+            srcFile.moveTo(destFile);
+            if (!isPreserveLastModified()
+                && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE))
+            {
+                destFile.getContent().setLastModifiedTime(System.currentTimeMillis());
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/ShowFileTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/ShowFileTask.java
new file mode 100644
index 0000000..7ce382e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/ShowFileTask.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.tools.ant.BuildException;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Date;
+
+/**
+ * An Ant task that writes the details of a file to Ant's log.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class ShowFileTask
+    extends VfsTask
+{
+    private static final String INDENT = "  ";
+    private String url;
+    private boolean showContent;
+    private boolean recursive;
+
+
+    /**
+     * The URL of the file to display.
+     * @param url The url of the file.
+     */
+    public void setFile(final String url)
+    {
+        this.url = url;
+    }
+
+    /**
+     * Shows the content.  Assumes the content is text, encoded using the
+     * platform's default encoding.
+     * @param showContent true if the content should be shown.
+     */
+    public void setShowContent(final boolean showContent)
+    {
+        this.showContent = showContent;
+    }
+
+    /**
+     * Recursively shows the descendents of the file.
+     * @param recursive true if descendents should be shown.
+     */
+    public void setRecursive(final boolean recursive)
+    {
+        this.recursive = recursive;
+    }
+
+    /**
+     * Executes the task.
+     * @throws BuildException if any exception is thrown.
+     */
+    public void execute() throws BuildException
+    {
+        try
+        {
+            final FileObject file = resolveFile(url);
+            log("Details of " + file.getName().getURI());
+            showFile(file, INDENT);
+        }
+        catch (final Exception e)
+        {
+            throw new BuildException(e);
+        }
+    }
+
+    /**
+     * Logs the details of a file.
+     */
+    private void showFile(final FileObject file, final String prefix) throws Exception
+    {
+        // Write details
+        StringBuffer msg = new StringBuffer(prefix);
+        msg.append(file.getName().getBaseName());
+        if (file.exists())
+        {
+            msg.append(" (");
+            msg.append(file.getType().getName());
+            msg.append(")");
+        }
+        else
+        {
+            msg.append(" (unknown)");
+        }
+        log(msg.toString());
+
+        if (file.exists())
+        {
+            final String newPrefix = prefix + INDENT;
+            if (file.getType().hasContent())
+            {
+                final FileContent content = file.getContent();
+                log(newPrefix + "Content-Length: " + content.getSize());
+                log(newPrefix + "Last-Modified" + new Date(content.getLastModifiedTime()));
+                if (showContent)
+                {
+                    log(newPrefix + "Content:");
+                    logContent(file, newPrefix);
+                }
+            }
+            if (file.getType().hasChildren())
+            {
+                final FileObject[] children = file.getChildren();
+                for (int i = 0; i < children.length; i++)
+                {
+                    FileObject child = children[i];
+                    if (recursive)
+                    {
+                        showFile(child, newPrefix);
+                    }
+                    else
+                    {
+                        log(newPrefix + child.getName().getBaseName());
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Writes the content of the file to Ant log.
+     */
+    private void logContent(final FileObject file, final String prefix)
+        throws Exception
+    {
+        final InputStream instr = file.getContent().getInputStream();
+        try
+        {
+            final BufferedReader reader = new BufferedReader(new InputStreamReader(instr));
+            while (true)
+            {
+                final String line = reader.readLine();
+                if (line == null)
+                {
+                    break;
+                }
+                log(prefix + line);
+            }
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/SyncTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/SyncTask.java
new file mode 100644
index 0000000..c3b9846
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/SyncTask.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * A task that synchronises the destination folder to look exactly like
+ * the source folder (or folders).
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SyncTask
+    extends CopyTask
+{
+    /**
+     * Handles a destination for which there is no corresponding source file.
+     */
+    protected void handleMissingSourceFile(final FileObject destFile)
+        throws Exception
+    {
+        log("deleting " + destFile);
+        //destFile.delete( Selectors.SELECT_SELF );
+    }
+
+    /**
+     * Check if this task cares about destination files with a missing source
+     * file.
+     */
+    protected boolean detectMissingSourceFiles()
+    {
+        return true;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/VfsTask.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/VfsTask.java
new file mode 100644
index 0000000..d201af4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/VfsTask.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.tasks;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.StandardFileSystemManager;
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.SubBuildListener;
+import org.apache.tools.ant.Task;
+
+/**
+ * Base class for the VFS Ant tasks.  Takes care of creating a FileSystemManager,
+ * and for cleaning it up at the end of the build.  Also provides some
+ * utility methods.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class VfsTask
+    extends Task
+{
+    private static StandardFileSystemManager manager;
+
+    /**
+     * Resolves a URI to a file, relative to the project's base directory.
+     *
+     * @param uri The URI to resolve.
+     */
+    protected FileObject resolveFile(final String uri)
+        throws FileSystemException
+    {
+        if (manager == null)
+        {
+            StandardFileSystemManager mngr = new StandardFileSystemManager();
+            mngr.setLogger(new AntLogger());
+            mngr.init();
+            manager = mngr;
+            getProject().addBuildListener(new CloseListener());
+        }
+        return manager.resolveFile(getProject().getBaseDir(), uri);
+    }
+
+    /**
+     * Close the manager
+     */
+    protected void closeManager()
+    {
+        if (manager != null)
+        {
+            manager.close();
+            manager = null;
+        }
+    }
+
+    /**
+     * Closes the VFS manager when the project finishes.
+     */
+    private class CloseListener
+        implements SubBuildListener
+    {
+        public void subBuildStarted(BuildEvent buildEvent)
+        {
+        }
+
+        public void subBuildFinished(BuildEvent buildEvent)
+        {
+            closeManager();
+        }
+
+        public void buildFinished(BuildEvent event)
+        {
+            closeManager();
+        }
+
+        public void buildStarted(BuildEvent event)
+        {
+        }
+
+        public void messageLogged(BuildEvent event)
+        {
+        }
+
+        public void targetFinished(BuildEvent event)
+        {
+        }
+
+        public void targetStarted(BuildEvent event)
+        {
+        }
+
+        public void taskFinished(BuildEvent event)
+        {
+        }
+
+        public void taskStarted(BuildEvent event)
+        {
+        }
+    }
+
+    /**
+     * A commons-logging wrapper for Ant logging.
+     */
+    private class AntLogger
+        implements Log
+    {
+        public void debug(final Object o)
+        {
+            log(String.valueOf(o), Project.MSG_DEBUG);
+        }
+
+        public void debug(Object o, Throwable throwable)
+        {
+            debug(o);
+        }
+
+        public void error(Object o)
+        {
+            log(String.valueOf(o), Project.MSG_ERR);
+        }
+
+        public void error(Object o, Throwable throwable)
+        {
+            error(o);
+        }
+
+        public void fatal(Object o)
+        {
+            log(String.valueOf(o), Project.MSG_ERR);
+        }
+
+        public void fatal(Object o, Throwable throwable)
+        {
+            fatal(o);
+        }
+
+        public void info(Object o)
+        {
+            log(String.valueOf(o), Project.MSG_INFO);
+        }
+
+        public void info(Object o, Throwable throwable)
+        {
+            info(o);
+        }
+
+        public void trace(Object o)
+        {
+        }
+
+        public void trace(Object o, Throwable throwable)
+        {
+        }
+
+        public void warn(Object o)
+        {
+            log(String.valueOf(o), Project.MSG_WARN);
+        }
+
+        public void warn(Object o, Throwable throwable)
+        {
+            warn(o);
+        }
+
+        public boolean isDebugEnabled()
+        {
+            return true;
+        }
+
+        public boolean isErrorEnabled()
+        {
+            return true;
+        }
+
+        public boolean isFatalEnabled()
+        {
+            return true;
+        }
+
+        public boolean isInfoEnabled()
+        {
+            return true;
+        }
+
+        public boolean isTraceEnabled()
+        {
+            return false;
+        }
+
+        public boolean isWarnEnabled()
+        {
+            return true;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/antlib.xml b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/antlib.xml
new file mode 100644
index 0000000..2334889
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/antlib.xml
@@ -0,0 +1,24 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<antlib>
+    <taskdef name="copy" classname="org.apache.commons.vfs.tasks.CopyTask" onerror="report"/>
+    <taskdef name="delete" classname="org.apache.commons.vfs.tasks.DeleteTask" onerror="report"/>
+    <taskdef name="mkdir" classname="org.apache.commons.vfs.tasks.MkdirTask" onerror="report"/>
+    <taskdef name="move" classname="org.apache.commons.vfs.tasks.MoveTask" onerror="report"/>
+    <taskdef name="show-file" classname="org.apache.commons.vfs.tasks.ShowFileTask" onerror="report"/>
+    <taskdef name="sync" classname="org.apache.commons.vfs.tasks.SyncTask" onerror="report"/>
+</antlib>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/package.html
new file mode 100644
index 0000000..fe92d83
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>The VFS Ant Tasks.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/tasks.properties b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/tasks.properties
new file mode 100644
index 0000000..e78f1f9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/tasks/tasks.properties
@@ -0,0 +1,21 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You under the Apache License, Version 2.0
+#   (the "License"); you may not use this file except in compliance with
+#   the License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+v-copy=org.apache.commons.vfs.tasks.CopyTask
+v-move=org.apache.commons.vfs.tasks.MoveTask
+v-sync=org.apache.commons.vfs.tasks.SyncTask
+v-delete=org.apache.commons.vfs.tasks.DeleteTask
+v-mkdir=org.apache.commons.vfs.tasks.MkdirTask
+v-show-file=org.apache.commons.vfs.tasks.ShowFileTask
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CombinedResources.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CombinedResources.java
new file mode 100644
index 0000000..2b8b2d6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CombinedResources.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+
+/**
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class CombinedResources extends ResourceBundle
+{
+    // locale.getLanguage()
+    // locale.getCountry()
+    // locale.getVariant()
+
+    private final String resourceName;
+    private boolean inited;
+    private final Properties properties = new Properties();
+
+    public CombinedResources(String resourceName)
+    {
+        this.resourceName = resourceName;
+    }
+
+    protected void init()
+    {
+        if (inited)
+        {
+            return;
+        }
+
+        loadResources(getResourceName());
+        loadResources(Locale.getDefault());
+        loadResources(getLocale());
+        inited = true;
+    }
+
+    protected void loadResources(Locale locale)
+    {
+        if (locale == null)
+        {
+            return;
+        }
+        String[] parts = new String[]{locale.getLanguage(), locale.getCountry(), locale.getVariant()};
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < 3; i++)
+        {
+            sb.append(getResourceName());
+            for (int j = 0; j < i; j++)
+            {
+                sb.append('_').append(parts[j]);
+            }
+            if (parts[i].length() != 0)
+            {
+                sb.append('_').append(parts[i]);
+                loadResources(sb.toString());
+            }
+            sb.setLength(0);
+        }
+    }
+
+    protected void loadResources(String resourceName)
+    {
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader == null)
+        {
+            loader = ClassLoader.getSystemClassLoader();
+        }
+        resourceName = resourceName.replace('.', '/') + ".properties";
+        try
+        {
+            Enumeration resources = loader.getResources(resourceName);
+            while (resources.hasMoreElements())
+            {
+                URL resource = (URL) resources.nextElement();
+                try
+                {
+                    properties.load(resource.openConnection().getInputStream());
+                }
+                catch (IOException e)
+                {
+                    // ignore
+                }
+            }
+        }
+        catch (IOException e)
+        {
+            // ignore
+        }
+    }
+
+    public String getResourceName()
+    {
+        return resourceName;
+    }
+
+    public Enumeration getKeys()
+    {
+        if (!inited)
+        {
+            init();
+        }
+        return properties.keys();
+    }
+
+    protected Object handleGetObject(String key)
+    {
+        if (!inited)
+        {
+            init();
+        }
+        return properties.get(key);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Cryptor.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Cryptor.java
new file mode 100644
index 0000000..211b331
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Cryptor.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+/**
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public interface Cryptor
+{
+    /**
+     * Encrypt the plain text password.
+     * @param plainKey The password.
+     * @return The encrypted password String.
+     * @throws Exception If an error occurs.
+     */
+    String encrypt(String plainKey) throws Exception;
+
+    /**
+     * Decrypts the password.
+     * @param encryptedKey the encrypted password.
+     * @return The plain text password.
+     * @throws Exception If an error occurs.
+     */
+    String decrypt(String encryptedKey) throws Exception;
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CryptorFactory.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CryptorFactory.java
new file mode 100644
index 0000000..6a12370
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/CryptorFactory.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+/**
+ * Factory to create an instance of a Cryptor.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public final class CryptorFactory
+{
+    /**
+     * The System property name to identify the Cryptor class to be used.
+     */
+    public static final String CRYPTOR_CLASS = "org.apache.commons.vfs.cryptor";
+
+    private static Cryptor instance;
+
+    /**
+     * Prevent instantiation of the class.
+     */
+    private CryptorFactory()
+    {
+
+    }
+
+    /**
+     * Allows the Cryptor class to be set programmatically.
+     * @param cryptor The Cryptor.
+     */
+    public static synchronized void setCryptor(Cryptor cryptor)
+    {
+        instance = cryptor;
+    }
+
+    /**
+     * Return the Cryptor. If one has not been previously set, create it. The Cryptor class
+     * can be set by setting the "org.apache.commons.vfs.cryptor" System property to the
+     * name of the Cryptor class.
+     * @return The Cryptor.
+     */
+    public static synchronized Cryptor getCryptor()
+    {
+        if (instance != null)
+        {
+            return instance;
+        }
+
+        String cryptorClass = System.getProperty(CRYPTOR_CLASS);
+        if (cryptorClass != null)
+        {
+            try
+            {
+                Class clazz = Class.forName(cryptorClass);
+                instance = (Cryptor) clazz.newInstance();
+                return instance;
+            }
+            catch (Exception ex)
+            {
+                throw new RuntimeException("Unable to create Cryptor " + cryptorClass, ex);
+            }
+        }
+        instance = new DefaultCryptor();
+        return instance;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DefaultCryptor.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DefaultCryptor.java
new file mode 100644
index 0000000..833cb41
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DefaultCryptor.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+/**
+ * Allows passwords to be encrypted and decrypted.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class DefaultCryptor implements Cryptor
+{
+    private static final char[] HEX_CHARS =
+            {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+    private static final byte[] KEY_BYTES = {0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x43, 0x6F, 0x6D, 0x6D,
+            0x6F, 0x6E, 0x73, 0x56, 0x46, 0x53};
+
+    private static final int INDEX_NOT_FOUND = -1;
+
+    private static final int BITS_IN_HALF_BYTE = 4;
+
+    private static final char MASK = 0x0f;
+
+    /**
+     * Encrypt the plain text password.
+     * @param plainKey The password.
+     * @return The encrypted password String.
+     * @throws Exception If an error occurs.
+     */
+    public String encrypt(String plainKey) throws Exception
+    {
+        byte[] input = plainKey.getBytes();
+        SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");
+
+        Cipher cipher = Cipher.getInstance("AES");
+
+        // encryption pass
+        cipher.init(Cipher.ENCRYPT_MODE, key);
+
+        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
+        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);
+        ctLength += cipher.doFinal(cipherText, ctLength);
+        return encode(cipherText);
+    }
+
+    /**
+     * Decrypts the password.
+     * @param encryptedKey the encrypted password.
+     * @return The plain text password.
+     * @throws Exception If an error occurs.
+     */
+    public String decrypt(String encryptedKey) throws Exception
+    {
+        SecretKeySpec key = new SecretKeySpec(KEY_BYTES, "AES");
+        Cipher cipher = Cipher.getInstance("AES");
+        cipher.init(Cipher.DECRYPT_MODE, key);
+        byte[] decoded = decode(encryptedKey);
+        byte[] plainText = new byte[cipher.getOutputSize(decoded.length)];
+        int ptLength = cipher.update(decoded, 0, decoded.length, plainText, 0);
+        ptLength += cipher.doFinal(plainText, ptLength);
+        return new String(plainText).substring(0, ptLength);
+    }
+
+    private String encode(byte[] bytes)
+    {
+        StringBuffer builder = new StringBuffer();
+
+        for (int i = 0; i < bytes.length; ++i)
+        {
+            builder.append(HEX_CHARS[(bytes[i] >> BITS_IN_HALF_BYTE) & MASK]);
+            builder.append(HEX_CHARS[bytes[i] & MASK]);
+        }
+        return builder.toString();
+    }
+
+    private byte[] decode(String str)
+    {
+        int length = str.length() / 2;
+        byte[] decoded = new byte[length];
+        char[] chars = str.toCharArray();
+        int index = 0;
+        for (int i = 0; i < chars.length; ++i)
+        {
+            int id1 = indexOf(HEX_CHARS, chars[i]);
+            if (id1 == -1)
+            {
+                throw new IllegalArgumentException("Character " + chars[i] + " at position " + i
+                        + " is not a valid hexidecimal character");
+            }
+            int id2 = indexOf(HEX_CHARS, chars[++i]);
+            if (id2 == -1)
+            {
+                throw new IllegalArgumentException("Character " + chars[i] + " at position " + i
+                        + " is not a valid hexidecimal character");
+            }
+            decoded[index++] = (byte) ((id1 << BITS_IN_HALF_BYTE) | id2);
+        }
+        return decoded;
+    }
+
+    private int indexOf(char[] array, char valueToFind)
+    {
+        if (array == null)
+        {
+            return INDEX_NOT_FOUND;
+        }
+        for (int i = 0; i < array.length; i++)
+        {
+            if (valueToFind == array[i])
+            {
+                return i;
+            }
+        }
+        return INDEX_NOT_FOUND;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilder.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilder.java
new file mode 100644
index 0000000..efc64a8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilder.java
@@ -0,0 +1,481 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * This class use reflection to set a configuration value using the fileSystemConfigBuilder
+ * associated the a scheme.<br><br>
+ * Example:<br>
+ * <pre>
+ * FileSystemOptions fso = new FileSystemOptions();
+ * DelegatingFileSystemOptionsBuilder delegate = new DelegatingFileSystemOptionsBuilder(VFS.getManager());
+ * delegate.setConfigString(fso, "sftp", "identities", "c:/tmp/test.ident");
+ * delegate.setConfigString(fso, "http", "proxyPort", "8080");
+ * delegate.setConfigClass(fso, "sftp", "userinfo", TrustEveryoneUserInfo.class);
+ * </pre>
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class DelegatingFileSystemOptionsBuilder
+{
+    private static final Class[] STRING_PARAM = new Class[]{String.class};
+
+    private static final Map PRIMATIVE_TO_OBJECT = new TreeMap();
+
+    private final Log log = LogFactory.getLog(DelegatingFileSystemOptionsBuilder.class);
+
+    private final FileSystemManager manager;
+
+    private final Map beanMethods = new TreeMap();
+
+    static
+    {
+        PRIMATIVE_TO_OBJECT.put(Void.TYPE.getName(), Void.class);
+        PRIMATIVE_TO_OBJECT.put(Boolean.TYPE.getName(), Boolean.class);
+        PRIMATIVE_TO_OBJECT.put(Byte.TYPE.getName(), Byte.class);
+        PRIMATIVE_TO_OBJECT.put(Character.TYPE.getName(), Character.class);
+        PRIMATIVE_TO_OBJECT.put(Short.TYPE.getName(), Short.class);
+        PRIMATIVE_TO_OBJECT.put(Integer.TYPE.getName(), Integer.class);
+        PRIMATIVE_TO_OBJECT.put(Long.TYPE.getName(), Long.class);
+        PRIMATIVE_TO_OBJECT.put(Double.TYPE.getName(), Double.class);
+        PRIMATIVE_TO_OBJECT.put(Float.TYPE.getName(), Float.class);
+    }
+
+    /**
+     * Context.
+     */
+    private static final class Context
+    {
+        private final FileSystemOptions fso;
+        private final String scheme;
+        private final String name;
+        private final Object[] values;
+
+        private List configSetters;
+        private FileSystemConfigBuilder fileSystemConfigBuilder;
+
+        private Context(final FileSystemOptions fso, final String scheme, final String name, final Object[] values)
+        {
+            this.fso = fso;
+            this.scheme = scheme;
+            this.name = name;
+            this.values = values;
+        }
+    }
+
+    /**
+     * Constructor.<br>
+     * Pass in your fileSystemManager instance.
+     *
+     * @param manager the manager to use to get the fileSystemConfigBuilder assocated to a scheme
+     */
+    public DelegatingFileSystemOptionsBuilder(final FileSystemManager manager)
+    {
+        this.manager = manager;
+    }
+
+    protected FileSystemManager getManager()
+    {
+        return manager;
+    }
+
+    /**
+     * Set a single string value.
+     *
+     * @param fso    FileSystemOptions
+     * @param scheme scheme
+     * @param name   name
+     * @param value  value
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setConfigString(final FileSystemOptions fso, final String scheme, final String name,
+                                final String value) throws FileSystemException
+    {
+        setConfigStrings(fso, scheme, name, new String[]{value});
+    }
+
+    /**
+     * Set an array of string value.
+     *
+     * @param fso    FileSystemOptions
+     * @param scheme scheme
+     * @param name   name
+     * @param values values
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setConfigStrings(final FileSystemOptions fso, final String scheme, final String name,
+                                 final String[] values) throws FileSystemException
+    {
+        Context ctx = new Context(fso, scheme, name, values);
+
+        setValues(ctx);
+    }
+
+    /**
+     * Set a single class value.<br>
+     * The class has to implement a no-args constructor, else the instantiation might fail.
+     *
+     * @param fso       FileSystemOptions
+     * @param scheme    scheme
+     * @param name      name
+     * @param className className
+     * @throws FileSystemException if an error occurs.
+     * @throws IllegalAccessException if a class canoot be accessed.
+     * @throws InstantiationException if a class cannot be instantiated.
+     */
+    public void setConfigClass(final FileSystemOptions fso, final String scheme, final String name,
+                               final Class className)
+            throws FileSystemException, IllegalAccessException, InstantiationException
+    {
+        setConfigClasses(fso, scheme, name, new Class[]{className});
+    }
+
+    /**
+     * Set an array of class values.<br>
+     * The class has to implement a no-args constructor, else the instantiation might fail.
+     *
+     * @param fso        FileSystemOptions
+     * @param scheme     scheme
+     * @param name       name
+     * @param classNames classNames
+     * @throws FileSystemException if an error occurs.
+     * @throws IllegalAccessException if a class canoot be accessed.
+     * @throws InstantiationException if a class cannot be instantiated.
+     */
+    public void setConfigClasses(final FileSystemOptions fso, final String scheme, final String name,
+                                 final Class[] classNames)
+            throws FileSystemException, IllegalAccessException, InstantiationException
+    {
+        Object[] values = new Object[classNames.length];
+        for (int iterClassNames = 0; iterClassNames < values.length; iterClassNames++)
+        {
+            values[iterClassNames] = classNames[iterClassNames].newInstance();
+        }
+
+        Context ctx = new Context(fso, scheme, name, values);
+
+        setValues(ctx);
+    }
+
+    /**
+     * sets the values using the informations of the given context.<br>
+     */
+    private void setValues(Context ctx) throws FileSystemException
+    {
+        // find all setter methods suitable for the given "name"
+        if (!fillConfigSetters(ctx))
+        {
+            throw new FileSystemException("vfs.provider/config-key-invalid.error", new String[]
+            {
+                ctx.scheme,
+                ctx.name
+            });
+        }
+
+        // get the fileSystemConfigBuilder
+        ctx.fileSystemConfigBuilder = getManager().getFileSystemConfigBuilder(ctx.scheme);
+
+        // try to find a setter which could accept the value
+        Iterator iterConfigSetters = ctx.configSetters.iterator();
+        while (iterConfigSetters.hasNext())
+        {
+            Method configSetter = (Method) iterConfigSetters.next();
+            if (convertValuesAndInvoke(configSetter, ctx))
+            {
+                return;
+            }
+        }
+
+        throw new FileSystemException("vfs.provider/config-value-invalid.error", new Object[]
+        {
+            ctx.scheme,
+            ctx.name,
+            ctx.values
+        });
+    }
+
+    /**
+     * tries to convert the value and pass it to the given method
+     */
+    private boolean convertValuesAndInvoke(final Method configSetter, final Context ctx) throws FileSystemException
+    {
+        Class[] parameters = configSetter.getParameterTypes();
+        if (parameters.length < 2)
+        {
+            return false;
+        }
+        if (!parameters[0].isAssignableFrom(FileSystemOptions.class))
+        {
+            return false;
+        }
+
+        Class valueParameter = parameters[1];
+        Class type;
+        if (valueParameter.isArray())
+        {
+            type = valueParameter.getComponentType();
+        }
+        else
+        {
+            if (ctx.values.length > 1)
+            {
+                return false;
+            }
+
+            type = valueParameter;
+        }
+
+        if (type.isPrimitive())
+        {
+            Class objectType = (Class) PRIMATIVE_TO_OBJECT.get(type.getName());
+            if (objectType == null)
+            {
+                log.warn(Messages.getString("vfs.provider/config-unexpected-primitive.error", type.getName()));
+                return false;
+            }
+            type = objectType;
+        }
+
+        Class valueClass = ctx.values[0].getClass();
+        if (type.isAssignableFrom(valueClass))
+        {
+            // can set value directly
+            invokeSetter(valueParameter, ctx, configSetter, ctx.values);
+            return true;
+        }
+        if (valueClass != String.class)
+        {
+            log.warn(Messages.getString("vfs.provider/config-unexpected-value-class.error", new String[]
+            {
+                valueClass.getName(),
+                ctx.scheme,
+                ctx.name
+            }));
+            return false;
+        }
+
+        Object convertedValues = java.lang.reflect.Array.newInstance(type, ctx.values.length);
+
+        Constructor valueConstructor;
+        try
+        {
+            valueConstructor = type.getConstructor(STRING_PARAM);
+        }
+        catch (NoSuchMethodException e)
+        {
+            valueConstructor = null;
+        }
+        if (valueConstructor != null)
+        {
+            // can convert using constructor
+            for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
+            {
+                try
+                {
+                    Array.set(convertedValues, iterValues,
+                            valueConstructor.newInstance(new Object[]{ctx.values[iterValues]}));
+                }
+                catch (InstantiationException e)
+                {
+                    throw new FileSystemException(e);
+                }
+                catch (IllegalAccessException e)
+                {
+                    throw new FileSystemException(e);
+                }
+                catch (InvocationTargetException e)
+                {
+                    throw new FileSystemException(e);
+                }
+            }
+
+            invokeSetter(valueParameter, ctx, configSetter, convertedValues);
+            return true;
+        }
+
+        Method valueFactory;
+        try
+        {
+            valueFactory = type.getMethod("valueOf", STRING_PARAM);
+            if (!Modifier.isStatic(valueFactory.getModifiers()))
+            {
+                valueFactory = null;
+            }
+        }
+        catch (NoSuchMethodException e)
+        {
+            valueFactory = null;
+        }
+
+        if (valueFactory != null)
+        {
+            // can convert using factory method (valueOf)
+            for (int iterValues = 0; iterValues < ctx.values.length; iterValues++)
+            {
+                try
+                {
+                    Array.set(convertedValues, iterValues,
+                            valueFactory.invoke(null, new Object[]{ctx.values[iterValues]}));
+                }
+                catch (IllegalAccessException e)
+                {
+                    throw new FileSystemException(e);
+                }
+                catch (InvocationTargetException e)
+                {
+                    throw new FileSystemException(e);
+                }
+            }
+
+            invokeSetter(valueParameter, ctx, configSetter, convertedValues);
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * invokes the method with the converted values
+     */
+    private void invokeSetter(Class valueParameter, final Context ctx, final Method configSetter, final Object values)
+        throws FileSystemException
+    {
+        Object[] args;
+        if (valueParameter.isArray())
+        {
+            args = new Object[]
+            {
+                ctx.fso,
+                values
+            };
+        }
+        else
+        {
+            args = new Object[]
+            {
+                ctx.fso,
+                Array.get(values, 0)
+            };
+        }
+        try
+        {
+            configSetter.invoke(ctx.fileSystemConfigBuilder, args);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new FileSystemException(e);
+        }
+        catch (InvocationTargetException e)
+        {
+            throw new FileSystemException(e);
+        }
+    }
+
+    /**
+     * fills all available set*() methods for the context-scheme into the context.
+     */
+    private boolean fillConfigSetters(final Context ctx)
+        throws FileSystemException
+    {
+        Map schemeMethods = getSchemeMethods(ctx.scheme);
+        List configSetters = (List) schemeMethods.get(ctx.name.toLowerCase());
+        if (configSetters == null)
+        {
+            return false;
+        }
+
+        ctx.configSetters = configSetters;
+        return true;
+    }
+
+    /**
+     * get (cached) list of set*() methods for the given scheme
+     */
+    private Map getSchemeMethods(final String scheme) throws FileSystemException
+    {
+        Map schemeMethods = (Map) beanMethods.get(scheme);
+        if (schemeMethods == null)
+        {
+            schemeMethods = createSchemeMethods(scheme);
+            beanMethods.put(scheme, schemeMethods);
+        }
+
+        return schemeMethods;
+    }
+
+    /**
+     * create the list of all set*() methods for the given scheme
+     */
+    private Map createSchemeMethods(String scheme) throws FileSystemException
+    {
+        final FileSystemConfigBuilder fscb = getManager().getFileSystemConfigBuilder(scheme);
+        if (fscb == null)
+        {
+            throw new FileSystemException("vfs.provider/no-config-builder.error", scheme);
+        }
+
+        Map schemeMethods = new TreeMap();
+
+        Method[] methods = fscb.getClass().getMethods();
+        for (int iterMethods = 0; iterMethods < methods.length; iterMethods++)
+        {
+            Method method = methods[iterMethods];
+            if (!Modifier.isPublic(method.getModifiers()))
+            {
+                continue;
+            }
+
+            String methodName = method.getName();
+            if (!methodName.startsWith("set"))
+            {
+                // not a setter
+                continue;
+            }
+
+            String key = methodName.substring(3).toLowerCase();
+
+            List configSetter = (List) schemeMethods.get(key);
+            if (configSetter == null)
+            {
+                configSetter = new ArrayList(2);
+                schemeMethods.put(key, configSetter);
+            }
+            configSetter.add(method);
+        }
+
+        return schemeMethods;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/EncryptUtil.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/EncryptUtil.java
new file mode 100644
index 0000000..308f3e8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/EncryptUtil.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+/**
+ * Allows passwords to be encrypted and decrypted.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public final class EncryptUtil
+{
+    /**
+     * Don't allow class instantiation.
+     */
+    private EncryptUtil()
+    {
+    }
+
+    /**
+     * This class can be called with "encrypt" password as the arguments where encrypt is
+     * a literal and password is replaced with the clear text password to be encrypted.
+     *
+     * @param args The arguments in the form "command" parm1, parm2.
+     * @throws Exception If an error occurs.
+     */
+    public static void main(String[] args) throws Exception
+    {
+        if (args.length != 2 || !(args[0].equals("encrypt")))
+        {
+            System.err.println("Usage: \"EncryptUtil encrypt\" password");
+            System.err.println("     password : The clear text password to encrypt");
+            System.exit(0);
+        }
+        Cryptor cryptor = CryptorFactory.getCryptor();
+
+        if (args[0].equals("encrypt"))
+        {
+            System.out.println(cryptor.encrypt(args[1]));
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/FileObjectUtils.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/FileObjectUtils.java
new file mode 100644
index 0000000..3852d2f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/FileObjectUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.DecoratedFileObject;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+
+/**
+ * Stuff to get some strange things from an FileObject.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class FileObjectUtils
+{
+    private FileObjectUtils()
+    {
+    }
+
+    /**
+     * Get access to the base object even if decorated.
+     * @param fileObject The FileObject.
+     * @return The decorated FileObject or null.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static AbstractFileObject getAbstractFileObject(final FileObject fileObject) throws FileSystemException
+    {
+        Object searchObject = fileObject;
+        while (searchObject instanceof DecoratedFileObject)
+        {
+            searchObject = ((DecoratedFileObject) searchObject).getDecoratedFileObject();
+        }
+        if (searchObject instanceof AbstractFileObject)
+        {
+            return (AbstractFileObject) searchObject;
+        }
+        if (searchObject == null)
+        {
+            return null;
+        }
+
+        throw new FileSystemException("vfs.util/find-abstract-file-object.error",
+                fileObject == null ? "null" : fileObject.getClass().getName());
+    }
+
+    /**
+     * Check if the given FileObject is instance of given class argument.
+     * @param fileObject The FileObject.
+     * @param wantedClass The Class to check.
+     * @return true if fileObject is an instance of the specified Class.
+     * @throws FileSystemException if an error occurs.
+     */
+    public static boolean isInstanceOf(final FileObject fileObject, final Class wantedClass) throws FileSystemException
+    {
+        Object searchObject = fileObject;
+        while (searchObject instanceof DecoratedFileObject)
+        {
+            if (wantedClass.isInstance(searchObject))
+            {
+                return true;
+            }
+
+            searchObject = ((DecoratedFileObject) searchObject).getDecoratedFileObject();
+        }
+
+        if (wantedClass.isInstance(searchObject))
+        {
+            return true;
+        }
+
+        return false;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Messages.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Messages.java
new file mode 100644
index 0000000..fd59012
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Messages.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Formats messages.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class Messages
+{
+    /**
+     * Map from message code to MessageFormat object for the message.
+     */
+    private static Map messages = new HashMap();
+    private static ResourceBundle resources;
+
+    private Messages()
+    {
+    }
+
+    /**
+     * Formats a message.
+     *
+     * @param code The message code.
+     * @return The formatted message.
+     */
+    public static String getString(final String code)
+    {
+        return getString(code, new Object[0]);
+    }
+
+    /**
+     * Formats a message.
+     *
+     * @param code  The message code.
+     * @param param The message parameter.
+     * @return The formatted message.
+     */
+    public static String getString(final String code, final Object param)
+    {
+        return getString(code, new Object[]{param});
+    }
+
+    /**
+     * Formats a message.
+     *
+     * @param code   The message code.
+     * @param params The message parameters.
+     * @return The formatted message.
+     */
+    public static String getString(final String code, final Object[] params)
+    {
+        try
+        {
+            if (code == null)
+            {
+                return null;
+            }
+
+            final MessageFormat msg = findMessage(code);
+            return msg.format(params);
+        }
+        catch (final MissingResourceException mre)
+        {
+            return "Unknown message with code \"" + code + "\".";
+        }
+    }
+
+    /**
+     * Locates a message by its code.
+     */
+    private static synchronized MessageFormat findMessage(final String code)
+        throws MissingResourceException
+    {
+        // Check if the message is cached
+        MessageFormat msg = (MessageFormat) messages.get(code);
+        if (msg != null)
+        {
+            return msg;
+        }
+
+        // Locate the message
+        if (resources == null)
+        {
+            resources = new CombinedResources("org.apache.commons.vfs.Resources");
+        }
+        final String msgText = resources.getString(code);
+        msg = new MessageFormat(msgText);
+        messages.put(code, msg);
+        return msg;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorInputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorInputStream.java
new file mode 100644
index 0000000..039ec27
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorInputStream.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An InputStream that provides buffering and end-of-stream monitoring.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class MonitorInputStream
+    extends BufferedInputStream
+{
+    private boolean finished;
+    private long count;
+
+    public MonitorInputStream(final InputStream in)
+    {
+        super(in);
+        count = 0;
+    }
+
+
+    /**
+     * Returns 0 if the stream is at eof, else the underlaying inputStream will be queried.
+     * @return The number of bytes that are available.
+     * @throws IOException if an error occurs.
+     */
+    public synchronized int available() throws IOException
+    {
+        if (finished)
+        {
+            return 0;
+        }
+
+        return super.available();
+    }
+
+    /**
+     * Reads a character.
+     * @return The character that was read as an integer.
+     * @throws IOException if an error occurs.
+     */
+    public int read() throws IOException
+    {
+        if (finished)
+        {
+            return -1;
+        }
+
+        final int ch = super.read();
+        if (ch != -1)
+        {
+            count++;
+            return ch;
+        }
+
+        // End-of-stream
+        close();
+        return -1;
+    }
+
+    /**
+     * Reads bytes from this input stream.
+     * @param buffer A byte array in which to place the characters read.
+     * @param offset The offset at which to start reading.
+     * @param length The maximum number of bytes to read.
+     * @return The number of bytes read.
+     * @throws IOException if an error occurs.
+     */
+    public int read(final byte[] buffer, final int offset, final int length)
+        throws IOException
+    {
+        if (finished)
+        {
+            return -1;
+        }
+
+        final int nread = super.read(buffer, offset, length);
+        if (nread != -1)
+        {
+            count += nread;
+            return nread;
+        }
+
+        // End-of-stream
+        close();
+        return -1;
+    }
+
+    /**
+     * Closes this input stream and releases any system resources
+     * associated with the stream.
+     * @throws IOException if an error occurs.
+     */
+    public void close() throws IOException
+    {
+        if (finished)
+        {
+            return;
+        }
+
+        // Close the stream
+        IOException exc = null;
+        try
+        {
+            super.close();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        // Notify that the stream has been closed
+        try
+        {
+            onClose();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        finished = true;
+        if (exc != null)
+        {
+            throw exc;
+        }
+    }
+
+    /**
+     * Called after the stream has been closed.  This implementation does
+     * nothing.
+     * @throws IOException if an error occurs.
+     */
+    protected void onClose() throws IOException
+    {
+    }
+
+    /**
+     * Get the nuber of bytes read by this input stream.
+     * @return The number of bytes read by this input stream.
+     */
+    public long getCount()
+    {
+        return count;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorOutputStream.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorOutputStream.java
new file mode 100644
index 0000000..9d96645
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorOutputStream.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.FileSystemException;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * An OutputStream that provides buffering and end-of-stream monitoring.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class MonitorOutputStream
+    extends BufferedOutputStream
+{
+    private boolean finished;
+
+    public MonitorOutputStream(final OutputStream out)
+    {
+        super(out);
+    }
+
+    /**
+     * Closes this output stream.
+     * @throws IOException if an error occurs.
+     */
+    public void close() throws IOException
+    {
+        if (finished)
+        {
+            return;
+        }
+
+        // Close the output stream
+        IOException exc = null;
+        try
+        {
+            super.close();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        // Notify of end of output
+        try
+        {
+            onClose();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        finished = true;
+
+        if (exc != null)
+        {
+            throw exc;
+        }
+    }
+
+
+    public synchronized void write(int b) throws IOException
+    {
+        assertOpen();
+        super.write(b);
+    }
+
+    public synchronized void write(byte[] b, int off, int len) throws IOException
+    {
+        assertOpen();
+        super.write(b, off, len);
+    }
+
+    public synchronized void flush() throws IOException
+    {
+        assertOpen();
+        super.flush();
+    }
+
+    public void write(byte[] b) throws IOException
+    {
+        assertOpen();
+        super.write(b);
+    }
+
+    /**
+     * check if file is still open. <br />
+     * This is a workaround for an oddidy with javas BufferedOutputStream where you can write to
+     * even if the stream has been closed
+     */
+    protected void assertOpen() throws FileSystemException
+    {
+        if (finished)
+        {
+            throw new FileSystemException("vfs.provider/closed.error");
+        }
+    }
+
+    /**
+     * Called after this stream is closed.  This implementation does nothing.
+     */
+    protected void onClose() throws IOException
+    {
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorRandomAccessContent.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorRandomAccessContent.java
new file mode 100644
index 0000000..380f738
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/MonitorRandomAccessContent.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.RandomAccessContent;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An RandomAccessContent that provides end-of-stream monitoring.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class MonitorRandomAccessContent implements RandomAccessContent
+{
+    private final RandomAccessContent content;
+    private boolean finished;
+
+    public MonitorRandomAccessContent(final RandomAccessContent content)
+    {
+        this.content = content;
+    }
+
+    /**
+     * Called after this stream is closed.  This implementation does nothing.
+     */
+    protected void onClose() throws IOException
+    {
+    }
+
+    /**
+     * Closes this content.
+     * @throws IOException if an error occurs.
+     */
+    public void close() throws IOException
+    {
+        if (finished)
+        {
+            return;
+        }
+
+        // Close the output stream
+        IOException exc = null;
+        try
+        {
+            content.close();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        // Notify of end of output
+        exc = null;
+        try
+        {
+            onClose();
+        }
+        catch (final IOException ioe)
+        {
+            exc = ioe;
+        }
+
+        finished = true;
+
+        if (exc != null)
+        {
+            throw exc;
+        }
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return content.getFilePointer();
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        content.seek(pos);
+    }
+
+    public long length() throws IOException
+    {
+        return content.length();
+    }
+
+    public void write(int b) throws IOException
+    {
+        content.write(b);
+    }
+
+    public void write(byte[] b) throws IOException
+    {
+        content.write(b);
+    }
+
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        content.write(b, off, len);
+    }
+
+    public void writeBoolean(boolean v) throws IOException
+    {
+        content.writeBoolean(v);
+    }
+
+    public void writeByte(int v) throws IOException
+    {
+        content.writeByte(v);
+    }
+
+    public void writeShort(int v) throws IOException
+    {
+        content.writeShort(v);
+    }
+
+    public void writeChar(int v) throws IOException
+    {
+        content.writeChar(v);
+    }
+
+    public void writeInt(int v) throws IOException
+    {
+        content.writeInt(v);
+    }
+
+    public void writeLong(long v) throws IOException
+    {
+        content.writeLong(v);
+    }
+
+    public void writeFloat(float v) throws IOException
+    {
+        content.writeFloat(v);
+    }
+
+    public void writeDouble(double v) throws IOException
+    {
+        content.writeDouble(v);
+    }
+
+    public void writeBytes(String s) throws IOException
+    {
+        content.writeBytes(s);
+    }
+
+    public void writeChars(String s) throws IOException
+    {
+        content.writeChars(s);
+    }
+
+    public void writeUTF(String str) throws IOException
+    {
+        content.writeUTF(str);
+    }
+
+    public void readFully(byte[] b) throws IOException
+    {
+        content.readFully(b);
+    }
+
+    public void readFully(byte[] b, int off, int len) throws IOException
+    {
+        content.readFully(b, off, len);
+    }
+
+    public int skipBytes(int n) throws IOException
+    {
+        return content.skipBytes(n);
+    }
+
+    public boolean readBoolean() throws IOException
+    {
+        return content.readBoolean();
+    }
+
+    public byte readByte() throws IOException
+    {
+        return content.readByte();
+    }
+
+    public int readUnsignedByte() throws IOException
+    {
+        return content.readUnsignedByte();
+    }
+
+    public short readShort() throws IOException
+    {
+        return content.readShort();
+    }
+
+    public int readUnsignedShort() throws IOException
+    {
+        return content.readUnsignedShort();
+    }
+
+    public char readChar() throws IOException
+    {
+        return content.readChar();
+    }
+
+    public int readInt() throws IOException
+    {
+        return content.readInt();
+    }
+
+    public long readLong() throws IOException
+    {
+        return content.readLong();
+    }
+
+    public float readFloat() throws IOException
+    {
+        return content.readFloat();
+    }
+
+    public double readDouble() throws IOException
+    {
+        return content.readDouble();
+    }
+
+    public String readLine() throws IOException
+    {
+        return content.readLine();
+    }
+
+    public String readUTF() throws IOException
+    {
+        return content.readUTF();
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return content.getInputStream();
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Os.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Os.java
new file mode 100644
index 0000000..2dac950
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/Os.java
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * Class to help determining the OS.
+ *
+ * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
+ * @author <a href="mailto:umagesh@apache.org">Magesh Umasankar</a>
+ * @author <a href="mailto:peter@apache.org">Peter Donald</a>
+ */
+public final class Os
+{
+    /**
+     * All Windows based OSes.
+     */
+    public static final OsFamily OS_FAMILY_WINDOWS = new OsFamily("windows");
+
+    /**
+     * All DOS based OSes.
+     */
+    public static final OsFamily OS_FAMILY_DOS = new OsFamily("dos");
+
+    /**
+     * All Windows NT based OSes.
+     */
+    public static final OsFamily OS_FAMILY_WINNT =
+        new OsFamily("nt", new OsFamily[]{OS_FAMILY_WINDOWS});
+
+    /**
+     * All Windows 9x based OSes.
+     */
+    public static final OsFamily OS_FAMILY_WIN9X =
+        new OsFamily("win9x", new OsFamily[]{OS_FAMILY_WINDOWS, OS_FAMILY_DOS});
+
+    /**
+     * OS/2.
+     */
+    public static final OsFamily OS_FAMILY_OS2 =
+        new OsFamily("os/2", new OsFamily[]{OS_FAMILY_DOS});
+
+    /**
+     * Netware.
+     */
+    public static final OsFamily OS_FAMILY_NETWARE =
+        new OsFamily("netware");
+
+    /**
+     * All UNIX based OSes.
+     */
+    public static final OsFamily OS_FAMILY_UNIX = new OsFamily("unix");
+
+    /**
+     * All Mac based OSes.
+     */
+    public static final OsFamily OS_FAMILY_MAC = new OsFamily("mac");
+
+    /**
+     * OSX.
+     */
+    public static final OsFamily OS_FAMILY_OSX =
+        new OsFamily("osx", new OsFamily[]{OS_FAMILY_UNIX, OS_FAMILY_MAC});
+
+    private static final String OS_NAME =
+        System.getProperty("os.name").toLowerCase(Locale.US);
+    private static final String OS_ARCH =
+        System.getProperty("os.arch").toLowerCase(Locale.US);
+    private static final String OS_VERSION =
+        System.getProperty("os.version").toLowerCase(Locale.US);
+    private static final String PATH_SEP =
+        System.getProperty("path.separator");
+    private static final OsFamily OS_FAMILY;
+    private static final OsFamily[] OS_ALL_FAMILIES;
+
+    private static final OsFamily[] ALL_FAMILIES = new OsFamily[]
+    {
+        OS_FAMILY_DOS,
+        OS_FAMILY_MAC,
+        OS_FAMILY_NETWARE,
+        OS_FAMILY_OS2,
+        OS_FAMILY_OSX,
+        OS_FAMILY_UNIX,
+        OS_FAMILY_WINDOWS,
+        OS_FAMILY_WINNT,
+        OS_FAMILY_WIN9X
+    };
+
+    static
+    {
+        OS_FAMILY = determineOsFamily();
+        OS_ALL_FAMILIES = determineAllFamilies();
+    }
+
+    /**
+     * Private constructor to block instantiation.
+     */
+    private Os()
+    {
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * version.
+     * @param version The version to check.
+     * @return true if the version matches.
+     */
+    public static boolean isVersion(final String version)
+    {
+        return isOs((OsFamily) null, null, null, version);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * architecture.
+     * @param arch The architecture to check.
+     * @return true if the architecture mataches.
+     */
+    public static boolean isArch(final String arch)
+    {
+        return isOs((OsFamily) null, null, arch, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * family.
+     * @param family The family to check.
+     * @return true if the family matches.
+     */
+    public static boolean isFamily(final String family)
+    {
+        return isOs(family, null, null, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * family.
+     * @param family The family to check.
+     * @return true if the family matches.
+     */
+    public static boolean isFamily(final OsFamily family)
+    {
+        return isOs(family, null, null, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS name.
+     *
+     * @param name Description of Parameter
+     * @return The Name value
+     * @since 1.7
+     */
+    public static boolean isName(final String name)
+    {
+        return isOs((OsFamily) null, name, null, null);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * family, name, architecture and version.
+     *
+     * @param family  The OS family
+     * @param name    The OS name
+     * @param arch    The OS architecture
+     * @param version The OS version
+     * @return The Os value
+     */
+    public static boolean isOs(final String family,
+                               final String name,
+                               final String arch,
+                               final String version)
+    {
+        return isOs(getFamily(family), name, arch, version);
+    }
+
+    /**
+     * Determines if the OS on which Ant is executing matches the given OS
+     * family, name, architecture and version.
+     *
+     * @param family  The OS family
+     * @param name    The OS name
+     * @param arch    The OS architecture
+     * @param version The OS version
+     * @return The Os value
+     */
+    public static boolean isOs(final OsFamily family,
+                               final String name,
+                               final String arch,
+                               final String version)
+    {
+        if (family != null || name != null || arch != null || version != null)
+        {
+            final boolean isFamily = familyMatches(family);
+            final boolean isName = nameMatches(name);
+            final boolean isArch = archMatches(arch);
+            final boolean isVersion = versionMatches(version);
+
+            return isFamily && isName && isArch && isVersion;
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    /**
+     * Locates an OsFamily by name (case-insensitive).
+     *
+     * @param name The family name to lookup.
+     * @return the OS family, or null if not found.
+     */
+    public static OsFamily getFamily(final String name)
+    {
+        for (int i = 0; i < ALL_FAMILIES.length; i++)
+        {
+            final OsFamily osFamily = ALL_FAMILIES[i];
+            if (osFamily.getName().equalsIgnoreCase(name))
+            {
+                return osFamily;
+            }
+        }
+
+        return null;
+    }
+
+    private static boolean versionMatches(final String version)
+    {
+        boolean isVersion = true;
+        if (version != null)
+        {
+            isVersion = version.equalsIgnoreCase(OS_VERSION);
+        }
+        return isVersion;
+    }
+
+    private static boolean archMatches(final String arch)
+    {
+        boolean isArch = true;
+        if (arch != null)
+        {
+            isArch = arch.equalsIgnoreCase(OS_ARCH);
+        }
+        return isArch;
+    }
+
+    private static boolean nameMatches(final String name)
+    {
+        boolean isName = true;
+        if (name != null)
+        {
+            isName = name.equalsIgnoreCase(OS_NAME);
+        }
+        return isName;
+    }
+
+    private static boolean familyMatches(final OsFamily family)
+    {
+        if (family == null)
+        {
+            return false;
+        }
+        for (int i = 0; i < OS_ALL_FAMILIES.length; i++)
+        {
+            final OsFamily osFamily = OS_ALL_FAMILIES[i];
+            if (family == osFamily)
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static OsFamily[] determineAllFamilies()
+    {
+        // Determine all families the current OS belongs to
+        Set allFamilies = new HashSet();
+        if (OS_FAMILY != null)
+        {
+            List queue = new ArrayList();
+            queue.add(OS_FAMILY);
+            while (queue.size() > 0)
+            {
+                final OsFamily family = (OsFamily) queue.remove(0);
+                allFamilies.add(family);
+                final OsFamily[] families = family.getFamilies();
+                for (int i = 0; i < families.length; i++)
+                {
+                    OsFamily parent = families[i];
+                    queue.add(parent);
+                }
+            }
+        }
+        return (OsFamily[]) allFamilies.toArray(new OsFamily[allFamilies.size()]);
+    }
+
+    private static OsFamily determineOsFamily()
+    {
+        // Determine the most specific OS family
+        if (OS_NAME.indexOf("windows") > -1)
+        {
+            if (OS_NAME.indexOf("xp") > -1
+                || OS_NAME.indexOf("2000") > -1
+                || OS_NAME.indexOf("nt") > -1)
+            {
+                return OS_FAMILY_WINNT;
+            }
+            else
+            {
+                return OS_FAMILY_WIN9X;
+            }
+        }
+        else if (OS_NAME.indexOf("os/2") > -1)
+        {
+            return OS_FAMILY_OS2;
+        }
+        else if (OS_NAME.indexOf("netware") > -1)
+        {
+            return OS_FAMILY_NETWARE;
+        }
+        else if (OS_NAME.indexOf("mac") > -1)
+        {
+            if (OS_NAME.endsWith("x"))
+            {
+                return OS_FAMILY_OSX;
+            }
+            else
+            {
+                return OS_FAMILY_MAC;
+            }
+        }
+        else if (PATH_SEP.equals(":"))
+        {
+            return OS_FAMILY_UNIX;
+        }
+        else
+        {
+            return null;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/OsFamily.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/OsFamily.java
new file mode 100644
index 0000000..73e70af
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/OsFamily.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+/**
+ * An enumerated type, which represents an OS family.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public final class OsFamily
+{
+    private final String name;
+    private final OsFamily[] families;
+
+    OsFamily(final String name)
+    {
+        this.name = name;
+        families = new OsFamily[0];
+    }
+
+    OsFamily(final String name, final OsFamily[] families)
+    {
+        this.name = name;
+        this.families = families;
+    }
+
+    /**
+     * Returns the name of this family.
+     * @return The name of this family.
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+    /**
+     * Returns the OS families that this family belongs to.
+     * @return an array of OSFamily objects that this family belongs to.
+     */
+    public OsFamily[] getFamilies()
+    {
+        return families;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/RandomAccessMode.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/RandomAccessMode.java
new file mode 100644
index 0000000..accb40f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/RandomAccessMode.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+/**
+ * An enumerated type representing the modes of a random access content.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public final class RandomAccessMode
+{
+    /**
+     * read.
+     */
+    public static final RandomAccessMode READ = new RandomAccessMode(true, false);
+
+    /**
+     * read/write.
+     */
+    public static final RandomAccessMode READWRITE = new RandomAccessMode(true, true);
+
+
+    private final boolean read;
+    private final boolean write;
+
+    private RandomAccessMode(final boolean read, final boolean write)
+    {
+        this.read = read;
+        this.write = write;
+    }
+
+    public boolean requestRead()
+    {
+        return read;
+    }
+
+    public boolean requestWrite()
+    {
+        return write;
+    }
+
+    public String getModeString()
+    {
+        if (requestRead())
+        {
+            if (requestWrite())
+            {
+                return "rw"; // NON-NLS
+            }
+            else
+            {
+                return "r"; // NON-NLS
+            }
+        }
+        else if (requestWrite())
+        {
+            return "w"; // NON-NLS
+        }
+
+        return "";
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/UserAuthenticatorUtils.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/UserAuthenticatorUtils.java
new file mode 100644
index 0000000..da1dc2a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/UserAuthenticatorUtils.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
+
+/**
+ * Some helper methods used for authentication.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public final class UserAuthenticatorUtils
+{
+    private UserAuthenticatorUtils()
+    {
+    }
+
+    /**
+     * gets data of given type from the UserAuthenticationData or null if there is no data or data
+     * of this type available.
+     * @param data The UserAuthenticationData.
+     * @param type The type of the element to retrieve.
+     * @param overriddenValue The default value.
+     * @return The data of the given type as a character array or null if the data is not available.
+     */
+    public static char[] getData(UserAuthenticationData data, UserAuthenticationData.Type type,
+                                 char[] overriddenValue)
+    {
+        if (overriddenValue != null)
+        {
+            return overriddenValue;
+        }
+
+        if (data == null)
+        {
+            return null;
+        }
+
+        return data.getData(type);
+    }
+
+    /**
+     * if there is a authenticator the authentication will take place, else null will be reutrned.
+     * @param opts The FileSystemOptions.
+     * @param authenticatorTypes An array of types describing the data to be retrieved.
+     * @return A UserAuthenticationData object containing the data requested.
+     */
+    public static UserAuthenticationData authenticate(FileSystemOptions opts,
+                                                      UserAuthenticationData.Type[] authenticatorTypes)
+    {
+        UserAuthenticator auth = DefaultFileSystemConfigBuilder.getInstance().getUserAuthenticator(opts);
+        return authenticate(auth, authenticatorTypes);
+    }
+
+    /**
+     * if there is a authenticator the authentication will take place, else null will be reutrned.
+     * @param auth The UserAuthenticator.
+     * @param authenticatorTypes An array of types describing the data to be retrieved.
+     * @return A UserAuthenticationData object containing the data requested.
+     */
+    public static UserAuthenticationData authenticate(UserAuthenticator auth,
+                                                      UserAuthenticationData.Type[] authenticatorTypes)
+    {
+        if (auth == null)
+        {
+            return null;
+        }
+
+        return auth.requestAuthentication(authenticatorTypes);
+    }
+
+    /**
+     * Converts a string to a char array (null safe).
+     * @param string The String to convert.
+     * @return The character array.
+     */
+    public static char[] toChar(String string)
+    {
+        if (string == null)
+        {
+            return null;
+        }
+
+        return string.toCharArray();
+    }
+
+    /**
+     * cleanup the data in the UerAuthenticationData (null safe).
+     * @param authData The UserAuthenticationDAta.
+     */
+    public static void cleanup(UserAuthenticationData authData)
+    {
+        if (authData == null)
+        {
+            return;
+        }
+
+        authData.cleanup();
+    }
+
+    /**
+     * converts the given data to a string (null safe).
+     * @param data A character array containing the data to convert to a String.
+     * @return The String.
+     */
+    public static String toString(char[] data)
+    {
+        if (data == null)
+        {
+            return null;
+        }
+
+        return new String(data);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/WeakRefFileListener.java b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/WeakRefFileListener.java
new file mode 100644
index 0000000..00c51bf
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/WeakRefFileListener.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.FileChangeEvent;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * Wrap a listener with a WeakReference.
+ *
+ * @author <a href="mailto:doogie@brainfood.com">Adam Heath</a>
+ * @version $Revision: 262 $ $Date: 2006-12-20T09:14:53.055649Z $
+ */
+public class WeakRefFileListener implements FileListener
+{
+    private final FileSystem fs;
+    private final FileName name;
+    private final WeakReference listener;
+
+    protected WeakRefFileListener(final FileObject file, final FileListener listener)
+    {
+        this.fs = file.getFileSystem();
+        this.name = file.getName();
+        this.listener = new WeakReference(listener);
+    }
+
+    /**
+     * This will install the <code>listener</code> at the given <code>file</code>.
+     * @param file The FileObject to listen on.
+     * @param listener The FileListener
+     */
+    public static void installListener(final FileObject file, final FileListener listener)
+    {
+        WeakRefFileListener weakListener = new WeakRefFileListener(file, listener);
+
+        file.getFileSystem().addListener(file, new WeakRefFileListener(file, weakListener));
+    }
+
+    /**
+     * returns the wrapped listener. If it is gone, the WeakRefFileListener wrapper will
+     * remove itself from the list of listeners.
+     * @return The FileListener.
+     * @throws Exception if an error occurs.
+     */
+    protected FileListener getListener() throws Exception
+    {
+        FileListener listener = (FileListener) this.listener.get();
+        if (listener == null)
+        {
+            FileObject file = fs.resolveFile(name);
+            file.getFileSystem().removeListener(file, this);
+        }
+        return listener;
+    }
+
+    /**
+     * Called when a file is created.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileCreated(final FileChangeEvent event) throws Exception
+    {
+        FileListener listener = getListener();
+        if (listener == null)
+        {
+            return;
+        }
+        listener.fileCreated(event);
+    }
+
+    /**
+     * Called when a file is deleted.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileDeleted(final FileChangeEvent event) throws Exception
+    {
+        FileListener listener = getListener();
+        if (listener == null)
+        {
+            return;
+        }
+        listener.fileDeleted(event);
+    }
+
+    /**
+     * Called when a file is changed.
+     * <p/>
+     * This will only happen if you monitor the file using {@link org.apache.commons.vfs.FileMonitor}.
+     * @param event The FileChangeEvent.
+     * @throws Exception if an error occurs.
+     */
+    public void fileChanged(FileChangeEvent event) throws Exception
+    {
+        FileListener listener = getListener();
+        if (listener == null)
+        {
+            return;
+        }
+        listener.fileChanged(event);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/package.html b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/package.html
new file mode 100644
index 0000000..3ce2f88
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/java/org/apache/commons/vfs/util/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>Utility classes used by the VFS.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/main/utils/create_archives.sh b/VFS-2.0-RC1/core/src/main/utils/create_archives.sh
new file mode 100755
index 0000000..e1fef2d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/main/utils/create_archives.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+##   Licensed to the Apache Software Foundation (ASF) under one or more
+##   contributor license agreements.  See the NOTICE file distributed with
+##   this work for additional information regarding copyright ownership.
+##   The ASF licenses this file to You under the Apache License, Version 2.0
+##   (the "License"); you may not use this file except in compliance with
+##   the License.  You may obtain a copy of the License at
+## 
+##       http://www.apache.org/licenses/LICENSE-2.0
+## 
+##   Unless required by applicable law or agreed to in writing, software
+##   distributed under the License is distributed on an "AS IS" BASIS,
+##   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+##   See the License for the specific language governing permissions and
+##   limitations under the License.
+
+PRG="$0"
+
+while [ -h "$PRG" ]; do
+  ls=`ls -ld "$PRG"`
+  link=`expr "$ls" : '.*-> \(.*\)$'`
+  if expr "$link" : '.*/.*' > /dev/null; then
+    PRG="$link"
+  else
+    PRG=`dirname "$PRG"`/"$link"
+  fi
+done
+
+# Get standard environment variables
+PRGDIR=`dirname "$PRG"`
+
+cd $PRGDIR/../..
+
+if [ ! -d target/test-data/read-tests ]
+then
+	echo "Please run maven to have the environment setup correctly"
+	exit 1
+fi
+
+if [ ! -x "`type -p jar`" ]
+then
+	echo "cant execute jar?"
+	exit 1
+fi
+if [ ! -x "`type -p tar`" ]
+then
+	echo "cant execute tar?"
+	exit 1
+fi
+if [ ! -x "`type -p zip`" ]
+then
+	echo "cant execute zip?"
+	exit 1
+fi
+
+cd target/test-data
+
+rm -f test.jar test.tar test.tbz2 test.tgz test.zip
+rm -f nested.jar nested.tar nested.tbz2 nested.tgz nested.zip
+
+echo "Creating test.jar ..."
+jar -cvfm test.jar test.mf read-tests code
+
+echo "Creating test.tar ..."
+tar cvf test.tar read-tests code
+
+echo "Creating test.tbz2 ..."
+tar cjvf test.tbz2 read-tests code
+
+echo "Creating test.tgz ..."
+tar czvf test.tgz read-tests code
+
+echo "Creating test.zip ..."
+zip -r test.zip read-tests code
+
+echo "Creating nested.jar ..."
+jar cvf nested.jar test.jar
+
+echo "Creating nested.tar ..."
+tar cvf nested.tar test.tar
+
+echo "Creating nested.tbz2 ..."
+tar cjvf nested.tbz2 test.tbz2
+
+echo "Creating nested.tgz ..."
+tar czvf nested.tgz test.tgz
+
+echo "Creating nested.zip ..."
+zip nested.zip test.zip
+
+for i in test.jar test.tar test.tbz2 test.tgz test.zip nested.jar nested.tar nested.tbz2 nested.tgz nested.zip
+do
+	cp $i ../../src/test-data/$i
+done
diff --git a/VFS-2.0-RC1/core/src/site/site.xml b/VFS-2.0-RC1/core/src/site/site.xml
new file mode 100644
index 0000000..61d4cb2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/site/site.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Commons&#xA0;VFS">
+
+  <bannerRight>
+    <name>Commons&#xA0;VFS</name>
+    <src>../images/vfs-logo-white.png</src>
+    <href>../index.html</href>
+  </bannerRight>
+
+  <body>
+    <links>
+      <item name="Commons VFS Home" href="../index.html"/>
+    </links>
+
+    <menu name="Commons&#xA0;VFS">
+      <item name="Overview"                href="../index.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/VFS-2.0-RC1/core/src/test/java/code/ClassToLoad.java b/VFS-2.0-RC1/core/src/test/java/code/ClassToLoad.java
new file mode 100644
index 0000000..aba3e3a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/code/ClassToLoad.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package code;
+
+/**
+ * The test class for the VFS classloader.
+ *
+ * @author <a href="mailto:brian@mmmanager.org">Brian Olsen</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-28 22:15:24 -0800 (Tue, 28 Nov 2006) $
+ */
+public class ClassToLoad
+{
+    private String m_message = "**PRIVATE**";
+
+    public String toString()
+    {
+        return m_message;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/code/sealed/AnotherClass.java b/VFS-2.0-RC1/core/src/test/java/code/sealed/AnotherClass.java
new file mode 100644
index 0000000..492d57d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/code/sealed/AnotherClass.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package code.sealed;
+
+/**
+ * A test class for the ClassLoader tests.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-28 22:15:24 -0800 (Tue, 28 Nov 2006) $
+ */
+public class AnotherClass
+{
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/AbstractVfsTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/AbstractVfsTestCase.java
new file mode 100644
index 0000000..30d79e1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/AbstractVfsTestCase.java
@@ -0,0 +1,266 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons;
+
+import junit.framework.TestCase;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.util.Messages;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * A base class for VFS tests.  Provides utility methods for locating
+ * test resources.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractVfsTestCase
+    extends TestCase
+{
+    private static File baseDir;
+
+    /** URL pattern */
+    private static final Pattern URL_PATTERN = Pattern.compile("[a-z]+://.*");
+
+    /** Password pattern */
+    private static final Pattern PASSWORD_PATTERN = Pattern.compile(":(?:[^/]+)@");
+
+    /**
+     * Returns the name of the package containing a class.
+     *
+     * @return The . delimited package name, or an empty string if the class
+     *         is in the default package.
+     */
+    public static String getPackageName(final Class clazz)
+    {
+        final Package pkg = clazz.getPackage();
+        if (null != pkg)
+        {
+            return pkg.getName();
+        }
+
+        final String name = clazz.getName();
+        if (-1 == name.lastIndexOf("."))
+        {
+            return "";
+        }
+        else
+        {
+            return name.substring(0, name.lastIndexOf("."));
+        }
+    }
+
+    /**
+     * Locates a test resource, and asserts that the resource exists
+     *
+     * @param name path of the resource, relative to this test's base directory.
+     */
+    public static File getTestResource(final String name)
+    {
+        return getTestResource(name, true);
+    }
+
+    /**
+     * Locates a test resource.
+     *
+     * @param name path of the resource, relative to this test's base directory.
+     */
+    public static File getTestResource(final String name, final boolean mustExist)
+    {
+        File file = new File(getTestDirectoryFile(), name);
+        file = getCanonicalFile(file);
+        if (mustExist)
+        {
+            assertTrue("Test file \"" + file + "\" does not exist.", file.exists());
+        }
+        else
+        {
+            assertTrue("Test file \"" + file + "\" should not exist.", !file.exists());
+        }
+
+        return file;
+    }
+
+    /**
+     * Locates the base directory for this test.
+     */
+    public static File getTestDirectoryFile()
+    {
+        if (baseDir == null)
+        {
+            // final String baseDirProp = System.getProperty("test.basedir");
+            final String baseDirProp = getTestDirectory();
+            baseDir = getCanonicalFile(new File(baseDirProp));
+        }
+        return baseDir;
+    }
+
+    public static String getTestDirectory()
+    {
+        return System.getProperty("test.basedir", "target/test-classes/test-data");
+    }
+
+    public static String getResourceTestDirectory()
+    {
+        return System.getProperty("test.basedir.res", "test-data");
+    }
+
+    /**
+     * Locates a test directory, creating it if it does not exist.
+     *
+     * @param name path of the directory, relative to this test's base directory.
+     */
+    public static File getTestDirectory(final String name)
+    {
+        File file = new File(getTestDirectoryFile(), name);
+        file = getCanonicalFile(file);
+        assertTrue("Test directory \"" + file + "\" does not exist or is not a directory.",
+            file.isDirectory() || file.mkdirs());
+        return file;
+    }
+
+    /**
+     * Makes a file canonical
+     */
+    public static File getCanonicalFile(final File file)
+    {
+        try
+        {
+            return file.getCanonicalFile();
+        }
+        catch (IOException e)
+        {
+            return file.getAbsoluteFile();
+        }
+    }
+
+    /**
+     * Asserts that an exception chain contains the expected messages.
+     *
+     * @param messages The messages, in order.  A null entry in this array
+     *                 indicates that the message should be ignored.
+     */
+    public static void assertSameMessage(final String[] messages, final Throwable throwable)
+    {
+        Throwable current = throwable;
+        for (int i = 0; i < messages.length; i++)
+        {
+            String message = messages[i];
+            assertNotNull(current);
+            if (message != null)
+            {
+                assertEquals(message, current.getMessage());
+            }
+
+            // Get the next exception in the chain
+            current = getCause(current);
+        }
+    }
+
+    /**
+     * Returns the cause of an exception.
+     */
+    public static Throwable getCause(Throwable throwable)
+    {
+        try
+        {
+            Method method = throwable.getClass().getMethod("getCause", (Class[]) null);
+            return (Throwable) method.invoke(throwable, (Object[]) null);
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Asserts that an exception contains the expected message.
+     */
+    public static void assertSameMessage(final String code,
+                                         final Throwable throwable)
+    {
+        assertSameMessage(code, new Object[0], throwable);
+    }
+
+    /**
+     * Asserts that an exception contains the expected message.
+     */
+    public static void assertSameMessage(final String code,
+                                         final Object[] params,
+                                         final Throwable throwable)
+    {
+        Object[] parmArray = params;
+        if (throwable instanceof FileSystemException)
+        {
+            final FileSystemException fse = (FileSystemException) throwable;
+
+            // Compare message code and params
+            assertEquals(code, fse.getCode());
+            assertEquals(params.length, fse.getInfo().length);
+            parmArray = new Object[params.length];
+            for (int i = 0; i < params.length; i++)
+            {
+                String value = String.valueOf(params[i]);
+                // mask passwords (VFS-169)
+                final Matcher urlMatcher = URL_PATTERN.matcher(value);
+                if (urlMatcher.find())
+                {
+                    final Matcher pwdMatcher = PASSWORD_PATTERN.matcher(value);
+                    value = pwdMatcher.replaceFirst(":***@");
+                }
+                assertEquals(value, fse.getInfo()[i]);
+                parmArray[i] = value;
+            }
+        }
+
+        // Compare formatted message
+        final String message = Messages.getString(code, parmArray);
+        assertEquals(message, throwable.getMessage());
+    }
+
+    /**
+     * Asserts that an exception contains the expected message.
+     */
+    public static void assertSameMessage(final String code,
+                                         final Object param,
+                                         final Throwable throwable)
+    {
+        assertSameMessage(code, new Object[]{param}, throwable);
+    }
+
+    /**
+     * Compares 2 objects for equality, nulls are equal.  Used by the test
+     * classes' equals() methods.
+     */
+    public static boolean equals(final Object o1, final Object o2)
+    {
+        if (o1 == null && o2 == null)
+        {
+            return true;
+        }
+        if (o1 == null || o2 == null)
+        {
+            return false;
+        }
+        return o1.equals(o2);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/FileSystemExceptionTest.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/FileSystemExceptionTest.java
new file mode 100644
index 0000000..5aca2cb
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/FileSystemExceptionTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import junit.framework.TestCase;
+
+
+/**
+ * Tests the {@link FileSystemException}.
+ * 
+ * @author J&ouml;rg Schaible
+ */
+public class FileSystemExceptionTest extends TestCase {
+    /**
+     * Tests a {@link FileSystemException} containing info with a URL containing a complete
+     * basic authentication.
+     */
+    public void testMasksPasswordOfUrlsWithBasicAuthentication() {
+        final FileSystemException fse = new FileSystemException(
+            "vfs.provider/rename.error", new String[]{
+                "file://test.bin", "http://foo:bar@junit.org/test.bin"});
+
+        assertEquals("file://test.bin", fse.getInfo()[0]);
+        assertEquals("http://foo:***@junit.org/test.bin", fse.getInfo()[1]);
+    }
+
+    /**
+     * Tests a {@link FileSystemException} containing info with a URL containing only the user
+     * information.
+     */
+    public void testDoesNotModifyUrlsWithoutPassword() {
+        final FileSystemException fse = new FileSystemException(
+            "vfs.provider/delete.error", new String[]{"http://foo@junit.org/test.bin"});
+        assertEquals("http://foo@junit.org/test.bin", fse.getInfo()[0]);
+    }
+
+    /**
+     * Tests a {@link FileSystemException} containing info with a nested URL containing a
+     * complete basic authentication.
+     */
+    public void testProperDetectionOfUrl() {
+        final FileSystemException fse = new FileSystemException(
+            "vfs.provider/delete.error", new String[]{"zip:http://foo:bar@junit.org/test.bin"});
+        assertEquals("zip:http://foo:***@junit.org/test.bin", fse.getInfo()[0]);
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/RunTest.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/RunTest.java
new file mode 100644
index 0000000..c6b9f2e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/RunTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.util.Properties;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+public class RunTest
+{
+    public static void main(String[] args) throws Exception
+    {
+        final String ip = "192.168.0.128";
+
+        Properties props = System.getProperties();
+        props.setProperty("test.data.src", "src/test-data");
+        props.setProperty("test.basedir", "core/target/test-classes/test-data");
+        props.setProperty("test.basedir.res", "test-data");
+        props.setProperty("test.policy", "src/test-data/test.policy");
+        props.setProperty("test.secure", "false");
+        props.setProperty("test.smb.uri",
+                "smb://HOME\\vfsusr:vfs%2f%25\\te:st@" + ip  + "/vfsusr/vfstest");
+        props.setProperty("test.ftp.uri",
+                "ftp://vfsusr:vfs%2f%25\\te:st@" + ip + "/vfstest");
+        props.setProperty("test.http.uri", "http://" + ip + "/vfstest");
+        props.setProperty("test.webdav.uri",
+                "webdav://vfsusr:vfs%2f%25\\te:st@" + ip + "/vfstest");
+        props.setProperty("test.sftp.uri",
+                "sftp://vfsusr:vfs%2f%25\\te:st@" + ip + "/vfstest");
+
+        Test tests[] = new Test[]
+        {
+//          LocalProviderTestCase.suite(),
+//          FtpProviderTestCase.suite(),
+//          UrlProviderHttpTestCase.suite(),
+//          VirtualProviderTestCase.suite(),
+//          TemporaryProviderTestCase.suite(),
+//          UrlProviderTestCase.suite(),
+//          ResourceProviderTestCase.suite(),
+//          HttpProviderTestCase.suite(),
+//          SftpProviderTestCase.suite(),
+//          JarProviderTestCase.suite(),
+//          NestedJarTestCase.suite(),
+//          ZipProviderTestCase.suite(),
+//          NestedZipTestCase.suite(),
+//          TarProviderTestCase.suite(),
+//          TgzProviderTestCase.suite(),
+//          Tbz2ProviderTestCase.suite(),
+//          NestedTarTestCase.suite(),
+//          NestedTgzTestCase.suite(),
+//          NestedTbz2TestCase.suite(),
+//          RamProviderTestCase.suite(),
+
+// SmbProviderTestCase.suite(),
+// WebdavProviderTestCase.suite(),
+        };
+
+        TestResult result = new TestResult()
+        {
+            public void startTest(Test test)
+            {
+                System.out.println("start " + test);
+                System.out.flush();
+            }
+
+            public void endTest(Test test)
+            {
+                // System.err.println("end " + test);
+            }
+
+            public synchronized void addError(Test test, Throwable throwable)
+            {
+                // throw new RuntimeException(throwable.getMessage());
+                throwable.printStackTrace();
+            }
+
+            public synchronized void addFailure(Test test,
+                    AssertionFailedError assertionFailedError)
+            {
+                // throw new RuntimeException(assertionFailedError.getMessage());
+                assertionFailedError.printStackTrace();
+            }
+        };
+
+        for (int i = 0; i < tests.length; i++)
+        {
+            System.out.println("start test#" + i);
+            System.out.flush();
+
+            Test test = tests[i];
+            test.run(result);
+
+            // break;
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTestCase.java
new file mode 100644
index 0000000..bca9750
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTestCase.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.CacheTestSuite;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+
+import java.io.File;
+
+/**
+ * Tests the NullFilesCache
+ * 
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class LRUFilesCacheTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        CacheTestSuite suite = new CacheTestSuite(new LRUFilesCacheTestCase());
+        suite.addTests(LRUFilesCacheTests.class);
+        return suite;
+    }
+
+    public FilesCache getFilesCache()
+    {
+        return new LRUFilesCache(5);
+    }
+
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File testDir = AbstractVfsTestCase.getTestDirectoryFile();
+        return manager.toFileObject(testDir);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTests.java
new file mode 100644
index 0000000..dadc262
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/LRUFilesCacheTests.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+
+/**
+ * NullFilesCache
+ * 
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class LRUFilesCacheTests extends AbstractProviderTestCase
+{
+    public void testFilesCache() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // releaseable
+        FileObject dir1 = scratchFolder.resolveFile("dir1");
+
+        // avoid cache removal
+        FileObject dir2 = scratchFolder.resolveFile("dir2");
+        dir2.getContent();
+
+        // releaseable
+        FileObject dir3 = scratchFolder.resolveFile("dir3");
+
+        // releaseable
+        FileObject dir4 = scratchFolder.resolveFile("dir4");
+
+        // releaseable
+        FileObject dir5 = scratchFolder.resolveFile("dir5");
+
+        // releaseable
+        FileObject dir6 = scratchFolder.resolveFile("dir6");
+
+        // releaseable
+        FileObject dir7 = scratchFolder.resolveFile("dir7");
+
+        // releaseable
+        FileObject dir8 = scratchFolder.resolveFile("dir8");
+
+        // check if the cache still holds the right instance
+        FileObject dir2_2 = scratchFolder.resolveFile("dir2");
+        assertTrue(dir2 == dir2_2);
+
+        // check if the cache still holds the right instance
+        FileObject dir1_2 = scratchFolder.resolveFile("dir1");
+        assertFalse(dir1 == dir1_2);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTestCase.java
new file mode 100644
index 0000000..b8635b5
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTestCase.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.CacheTestSuite;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+
+import java.io.File;
+
+/**
+ * Tests the NullFilesCache
+ * 
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class NullFilesCacheTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        CacheTestSuite suite = new CacheTestSuite(new org.apache.commons.vfs.cache.NullFilesCacheTestCase());
+        suite.addTests(NullFilesCacheTests.class);
+        return suite;
+    }
+
+    public FilesCache getFilesCache()
+    {
+        return new NullFilesCache();
+    }
+
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File testDir = AbstractVfsTestCase.getTestDirectoryFile();
+        return manager.toFileObject(testDir);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTests.java
new file mode 100644
index 0000000..a09cbc3
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/cache/NullFilesCacheTests.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.cache;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+
+/**
+ * NullFilesCache
+ * 
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class NullFilesCacheTests extends AbstractProviderTestCase
+{
+    public void testFilesCache() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        FileObject dir1 = scratchFolder.resolveFile("dir1");
+        FileObject dir1_2 = scratchFolder.resolveFile("dir1");
+
+        assertFalse(dir1 == dir1_2);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/DefaultFileMonitorTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/DefaultFileMonitorTests.java
new file mode 100644
index 0000000..88e61bd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/DefaultFileMonitorTests.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl.test;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileChangeEvent;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.VFS;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.impl.DefaultFileMonitor;
+
+import java.io.File;
+import java.io.FileWriter;
+
+/**
+ * Test to verify DefaultFileMonitor
+ */
+public class DefaultFileMonitorTests extends AbstractVfsTestCase
+{
+    private FileSystemManager fsManager;
+    private File testDir;
+    private int changeStatus = 0;
+    private File testFile;
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        fsManager = VFS.getManager();
+        testDir = AbstractVfsTestCase.getTestDirectoryFile();
+        changeStatus = 0;
+        testFile = new File(testDir, "testReload.properties");
+
+        if (testFile.exists())
+        {
+            testFile.delete();
+        }
+    }
+
+    public void tearDown() throws Exception
+    {
+        if (testFile != null && testFile.exists())
+        {
+            testFile.delete();
+        }
+        super.tearDown();
+    }
+
+    public void testFileCreated() throws Exception
+    {
+        FileObject fileObj = fsManager.resolveFile(testFile.toURL().toString());
+        DefaultFileMonitor monitor = new DefaultFileMonitor(new TestFileListener());
+        monitor.setDelay(100);
+        monitor.addFile(fileObj);
+        monitor.start();
+        writeToFile(testFile);
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event", changeStatus == 3);
+        monitor.stop();
+    }
+
+    public void testFileDeleted() throws Exception
+    {
+        writeToFile(testFile);
+        FileObject fileObj = fsManager.resolveFile(testFile.toURL().toString());
+        DefaultFileMonitor monitor = new DefaultFileMonitor(new TestFileListener());
+        monitor.setDelay(100);
+        monitor.addFile(fileObj);
+        monitor.start();
+        testFile.delete();
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event", changeStatus == 2);
+        monitor.stop();
+    }
+
+    public void testFileModified() throws Exception
+    {
+        writeToFile(testFile);
+        FileObject fileObj = fsManager.resolveFile(testFile.toURL().toString());
+        DefaultFileMonitor monitor = new DefaultFileMonitor(new TestFileListener());
+        monitor.setDelay(100);
+        monitor.addFile(fileObj);
+        monitor.start();
+        // Need a long delay to insure the new timestamp doesn't truncate to be the same as
+        // the current timestammp. Java only guarantees the timestamp will be to 1 second.
+        Thread.sleep(1000);
+        long value = System.currentTimeMillis();
+        boolean rc = testFile.setLastModified(value);
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event", changeStatus == 1);
+        monitor.stop();
+    }
+
+
+    public void testFileRecreated() throws Exception
+    {
+        FileObject fileObj = fsManager.resolveFile(testFile.toURL().toString());
+        DefaultFileMonitor monitor = new DefaultFileMonitor(new TestFileListener());
+        monitor.setDelay(100);
+        monitor.addFile(fileObj);
+        monitor.start();
+        writeToFile(testFile);
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event " + changeStatus, changeStatus == 3);
+        changeStatus = 0;
+        testFile.delete();
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event " + changeStatus, changeStatus == 2);
+        changeStatus = 0;
+        Thread.sleep(500);
+        monitor.addFile(fileObj);
+        writeToFile(testFile);
+        Thread.sleep(300);
+        assertTrue("No event occurred", changeStatus != 0);
+        assertTrue("Incorrect event " + changeStatus, changeStatus == 3);
+        monitor.stop();
+    }
+
+    private void writeToFile(File file) throws Exception
+    {
+        FileWriter out = new FileWriter(file);
+        out.write("string=value1");
+        out.flush();
+        out.close();
+    }
+
+
+    public class TestFileListener implements FileListener
+    {
+        public void fileChanged(FileChangeEvent event) throws Exception
+        {
+            changeStatus = 1;
+        }
+
+        public void fileDeleted(FileChangeEvent event) throws Exception
+        {
+            changeStatus = 2;
+        }
+
+        public void fileCreated(FileChangeEvent event) throws Exception
+        {
+            changeStatus = 3;
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/VfsClassLoaderTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/VfsClassLoaderTests.java
new file mode 100644
index 0000000..2b55640
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/impl/test/VfsClassLoaderTests.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.impl.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.impl.VFSClassLoader;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * VfsClassLoader test cases.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class VfsClassLoaderTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.READ_CONTENT,
+            Capability.URI
+        };
+    }
+
+    /**
+     * Creates the classloader to use when testing.
+     */
+    private VFSClassLoader createClassLoader() throws FileSystemException
+    {
+        FileObject file = getBaseFolder();
+        final VFSClassLoader loader =
+            new VFSClassLoader(file , getManager());
+        return loader;
+    }
+
+    /**
+     * Tests loading a class.
+     */
+    public void testLoadClass() throws Exception
+    {
+        final VFSClassLoader loader = createClassLoader();
+
+        final Class testClass = loader.loadClass("code.ClassToLoad");
+        final Package pack = testClass.getPackage();
+        assertEquals("code", pack.getName());
+        verifyPackage(pack, false);
+
+        final Object testObject = testClass.newInstance();
+        assertEquals("**PRIVATE**", testObject.toString());
+    }
+
+    /**
+     * Tests loading a resource.
+     */
+    public void testLoadResource() throws Exception
+    {
+        final VFSClassLoader loader = createClassLoader();
+
+        final URL resource = loader.getResource("read-tests/file1.txt");
+
+        assertNotNull(resource);
+        final URLConnection urlCon = resource.openConnection();
+        assertSameURLContent(FILE1_CONTENT, urlCon);
+    }
+
+    /**
+     * Tests package sealing.
+     */
+    public void testSealing() throws Exception
+    {
+        final VFSClassLoader loader = createClassLoader();
+        final Class testClass = loader.loadClass("code.sealed.AnotherClass");
+        final Package pack = testClass.getPackage();
+        assertEquals("code.sealed", pack.getName());
+        verifyPackage(pack, true);
+    }
+
+    /**
+     * Verify the package loaded with class loader.
+     */
+    private void verifyPackage(final Package pack,
+                               final boolean sealed)
+        throws FileSystemException
+    {
+        if (getBaseFolder().getFileSystem().hasCapability(Capability.MANIFEST_ATTRIBUTES))
+        {
+            assertEquals("ImplTitle", pack.getImplementationTitle());
+            assertEquals("ImplVendor", pack.getImplementationVendor());
+            assertEquals("1.1", pack.getImplementationVersion());
+            assertEquals("SpecTitle", pack.getSpecificationTitle());
+            assertEquals("SpecVendor", pack.getSpecificationVendor());
+            assertEquals("1.0", pack.getSpecificationVersion());
+            assertEquals(sealed, pack.isSealed());
+        }
+        else
+        {
+            assertNull(pack.getImplementationTitle());
+            assertNull(pack.getImplementationVendor());
+            assertNull(pack.getImplementationVersion());
+            assertNull(pack.getSpecificationTitle());
+            assertNull(pack.getSpecificationVendor());
+            assertNull(pack.getSpecificationVersion());
+            assertFalse(pack.isSealed());
+        }
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/perf/FileNamePerformance.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/perf/FileNamePerformance.java
new file mode 100644
index 0000000..93656d2
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/perf/FileNamePerformance.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.perf;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.VFS;
+
+public class FileNamePerformance
+{
+    private final static int NUOF_RESOLVES = 100000;
+
+    public static void main(String[] args) throws FileSystemException
+    {
+        FileSystemManager mgr = VFS.getManager();
+
+        FileObject root = mgr
+                .resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr");
+        FileName rootName = root.getName();
+    
+        testNames(mgr, rootName);
+
+        testChildren(root);
+
+        testFiles(mgr);
+    }
+
+    private static void testFiles(FileSystemManager mgr) throws FileSystemException
+    {
+        for (int i = 0; i < 10; i++)
+        {
+            // warmup jvm
+            mgr.resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < NUOF_RESOLVES; i++)
+        {
+            mgr.resolveFile("smb://HOME\\vfsusr:vfs%2f%25\\te:st@10.0.1.54/vfsusr/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+        long end = System.currentTimeMillis();
+
+        System.err.println("time to resolve " + NUOF_RESOLVES + " files: "
+                + (end - start) + "ms");
+    }
+
+    private static void testChildren(FileObject root) throws FileSystemException
+    {
+        for (int i = 0; i < 10; i++)
+        {
+            // warmup jvm
+            root.resolveFile("/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < NUOF_RESOLVES; i++)
+        {
+            root.resolveFile("/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+        long end = System.currentTimeMillis();
+
+        System.err.println("time to resolve " + NUOF_RESOLVES + " childs: "
+                + (end - start) + "ms");
+    }
+
+    private static void testNames(FileSystemManager mgr, FileName rootName) throws FileSystemException
+    {
+        for (int i = 0; i < 10; i++)
+        {
+            // warmup jvm
+            mgr.resolveName(rootName,
+                    "/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+
+        long start = System.currentTimeMillis();
+        for (int i = 0; i < NUOF_RESOLVES; i++)
+        {
+            mgr.resolveName(rootName,
+                    "/many/path/elements/with%25esc/any%25where/to/file.txt");
+        }
+        long end = System.currentTimeMillis();
+
+        System.err.println("time to resolve " + NUOF_RESOLVES + " names: "
+                + (end - start) + "ms");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ftp/test/FtpProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ftp/test/FtpProviderTestCase.java
new file mode 100644
index 0000000..7939bd9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ftp/test/FtpProviderTestCase.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ftp.test;
+
+import junit.framework.Test;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.ftp.FtpFileProvider;
+import org.apache.commons.vfs.provider.ftp.FtpFileSystemConfigBuilder;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for FTP file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class FtpProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    private static final String TEST_URI = "test.ftp.uri";
+    /**
+     * Creates the test suite for the ftp file system.
+     */
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            return new ProviderTestSuite(new FtpProviderTestCase());
+        }
+        else
+        {
+            return notConfigured(FtpProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        manager.addProvider("ftp", new FtpFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final String uri = System.getProperty(TEST_URI);
+        FileSystemOptions opts = new FileSystemOptions();
+        FtpFileSystemConfigBuilder.getInstance().setPassiveMode(opts, true);
+        return manager.resolveFile(uri, opts);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/http/test/HttpProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/http/test/HttpProviderTestCase.java
new file mode 100644
index 0000000..c27e432
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/http/test/HttpProviderTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.http.test;
+
+import junit.framework.Test;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.http.HttpFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Test cases for the HTTP provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class HttpProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    private static final String TEST_URI = "test.http.uri";
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            return new ProviderTestSuite(new HttpProviderTestCase());
+        }
+        else
+        {
+            return notConfigured(HttpProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("http", new HttpFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+        throws Exception
+    {
+        final String uri = System.getProperty(TEST_URI);
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/JarProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/JarProviderTestCase.java
new file mode 100644
index 0000000..1990bfd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/JarProviderTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.jar.JarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Jar file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class JarProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the jar file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new JarProviderTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("jar", new JarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File jarFile = AbstractVfsTestCase.getTestResource("test.jar");
+        final String uri = "jar:file:" + jarFile.getAbsolutePath() + "!/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/NestedJarTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/NestedJarTestCase.java
new file mode 100644
index 0000000..3b59599
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/jar/test/NestedJarTestCase.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.jar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.jar.JarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Zip file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class NestedJarTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for nested jar files.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new NestedJarTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("jar", new JarFileProvider());
+        manager.addExtensionMap("jar", "jar");
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        // Locate the Jar file
+        final File outerFile = AbstractVfsTestCase.getTestResource("nested.jar");
+        final String uri = "jar:file:" + outerFile.getAbsolutePath() + "!/test.jar";
+        final FileObject jarFile = manager.resolveFile(uri);
+
+        // Now build the nested file system
+        final FileObject nestedFS = manager.createFileSystem(jarFile);
+        return nestedFS.resolveFile("/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/FileNameTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/FileNameTests.java
new file mode 100644
index 0000000..4a899fc
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/FileNameTests.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local.test;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+
+import java.io.File;
+
+/**
+ * Additional naming tests for local file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileNameTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Tests resolution of an absolute file name.
+     */
+    public void testAbsoluteFileName() throws Exception
+    {
+        // Locate file by absolute file name
+        String fileName = new File("testdir").getAbsolutePath();
+        FileObject absFile = getManager().resolveFile(fileName);
+
+        // Locate file by URI
+        String uri = "file://" + fileName.replace(File.separatorChar, '/');
+        FileObject uriFile = getManager().resolveFile(uri);
+
+        assertSame("file object", absFile, uriFile);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/LocalProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/LocalProviderTestCase.java
new file mode 100644
index 0000000..533f971
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/local/test/LocalProviderTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.local.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the local file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class LocalProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the local file system.
+     */
+    public static Test suite() throws Exception
+    {
+        final ProviderTestSuite testSuite = new ProviderTestSuite(new LocalProviderTestCase());
+        testSuite.addTests(FileNameTests.class);
+        return testSuite;
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File testDir = AbstractVfsTestCase.getTestDirectoryFile();
+        return manager.toFileObject(testDir);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/CustomRamProviderTest.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/CustomRamProviderTest.java
new file mode 100644
index 0000000..ac41c74
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/CustomRamProviderTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram.test;
+
+import java.io.OutputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.ram.RamFileProvider;
+import org.apache.commons.vfs.provider.ram.RamFileSystemConfigBuilder;
+
+/**
+ * Custom tests
+ * 
+ * @author edgar poce
+ * @version
+ * 
+ */
+public class CustomRamProviderTest extends TestCase
+{
+    DefaultFileSystemManager manager;
+
+    FileSystemOptions zeroSized = new FileSystemOptions();
+
+    FileSystemOptions smallSized = new FileSystemOptions();
+
+    FileSystemOptions defaultRamFs = new FileSystemOptions();
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        manager = new DefaultFileSystemManager();
+        manager.addProvider("ram", new RamFileProvider());
+        manager.init();
+
+        // File Systems Options
+        RamFileSystemConfigBuilder.getInstance().setMaxSize(zeroSized, 0);
+        RamFileSystemConfigBuilder.getInstance().setMaxSize(smallSized, 10);
+    }
+
+    protected void tearDown() throws Exception
+    {
+        super.tearDown();
+        manager.close();
+    }
+
+    public void testSmallFS() throws Exception
+    {
+
+        // Default FS
+        FileObject fo1 = manager.resolveFile("ram:/");
+        FileObject fo2 = manager.resolveFile("ram:/");
+        assertTrue("Both files should exist in the same fs instance.", fo1
+                .getFileSystem() == fo2.getFileSystem());
+
+        // Small FS
+        FileObject fo3 = manager.resolveFile("ram:/fo3", smallSized);
+        FileObject fo4 = manager.resolveFile("ram:/", smallSized);
+        assertTrue("Both files should exist in different fs instances.", fo3
+                .getFileSystem() == fo4.getFileSystem());
+        assertTrue("These file shouldn't be in the same file system.", fo1
+                .getFileSystem() != fo3.getFileSystem());
+
+        fo3.createFile();
+        try
+        {
+            OutputStream os = fo3.getContent().getOutputStream();
+            os.write(new byte[10]);
+            os.close();
+        }
+        catch (FileSystemException e)
+        {
+            fail("It shouldn't save such a small file");
+        }
+
+        try
+        {
+            OutputStream os = fo3.getContent().getOutputStream();
+            os.write(new byte[11]);
+            os.close();
+            fail("It shouldn't save such a big file");
+        }
+        catch (FileSystemException e)
+        {
+            // exception awaited
+        }
+
+    }
+
+    /**
+     * 
+     * Checks root folder exists
+     * 
+     * @throws FileSystemException
+     */
+    public void testRootFolderExists() throws FileSystemException {
+        FileObject root = manager.resolveFile("ram:///", defaultRamFs);
+        assertTrue(root.getType().hasChildren());
+
+        try {
+            root.delete();
+            fail();
+        } catch (FileSystemException e) {
+            
+        }
+
+    }
+
+    
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/RamProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/RamProviderTestCase.java
new file mode 100644
index 0000000..fac40a9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/ram/test/RamProviderTestCase.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.ram.test;
+
+import java.io.File;
+
+import junit.framework.Test;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+import org.apache.commons.vfs.provider.ram.RamFileProvider;
+import org.apache.commons.vfs.provider.ram.RamFileSystem;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+import org.apache.commons.AbstractVfsTestCase;
+
+/**
+ * Tests for the RAM file system.
+ */
+public class RamProviderTestCase extends AbstractProviderTestConfig implements
+        ProviderTestConfig
+{
+    private boolean inited = false;
+
+    /** logger */
+    private static Log log = LogFactory.getLog(RamProviderTestCase.class);
+
+    /**
+     * Creates the test suite for the ram file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new RamProviderTestCase());
+    }
+
+    /**
+     * Prepares the file system manager.
+     * 
+     * Imports test data from the disk.
+     * 
+     * @throws Exception
+     * 
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+            throws Exception
+    {
+        try
+        {
+            manager.addProvider("ram", new RamFileProvider());
+            manager.addProvider("file", new DefaultLocalFileProvider());
+        }
+        catch (Exception e)
+        {
+            log.error(e);
+            throw e;
+        }
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+            throws Exception
+    {
+        if (!inited)
+        {
+            // Import the test tree
+            FileObject fo = manager.resolveFile("ram:/");
+            RamFileSystem fs = (RamFileSystem) fo.getFileSystem();
+            fs.importTree(new File(AbstractVfsTestCase.getTestDirectory()));
+            fo.close();
+            
+            inited=true;
+        }
+
+        final String uri = "ram:/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/res/test/ResourceProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/res/test/ResourceProviderTestCase.java
new file mode 100644
index 0000000..1bdb092
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/res/test/ResourceProviderTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.vfs.provider.res.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.jar.JarFileProvider;
+import org.apache.commons.vfs.provider.res.ResourceFileProvider;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Test cases for the resource provider.
+ *
+ * @author Emmanuel Bourg
+ * @version $Revision$, $Date$
+ */
+public class ResourceProviderTestCase extends AbstractProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new ResourceProviderTestCase());
+    }
+
+    /**
+     * Prepares the file system manager.  This implementation does nothing.
+     */
+    public void prepare(DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("res", new ResourceFileProvider());
+        manager.addProvider("file", new UrlFileProvider());
+        manager.addProvider("jar", new JarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(FileSystemManager manager)
+        throws Exception
+    {
+        String baseDir = AbstractVfsTestCase.getResourceTestDirectory();
+        return manager.resolveFile("res:" + baseDir);
+    }
+}
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/sftp/test/SftpProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/sftp/test/SftpProviderTestCase.java
new file mode 100644
index 0000000..345b01e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/sftp/test/SftpProviderTestCase.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.sftp.test;
+
+import junit.framework.Test;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.sftp.SftpFileProvider;
+import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
+import org.apache.commons.vfs.provider.sftp.TrustEveryoneUserInfo;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Test cases for the SFTP provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SftpProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    private static final String TEST_URI = "test.sftp.uri";
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            return new ProviderTestSuite(new SftpProviderTestCase());
+        }
+        else
+        {
+            return notConfigured(SftpProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("sftp", new SftpFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final String uri = System.getProperty(TEST_URI);
+
+        FileSystemOptions fileSystemOptions = new FileSystemOptions();
+        SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fileSystemOptions, "no");
+        SftpFileSystemConfigBuilder.getInstance().setUserInfo(fileSystemOptions, new TrustEveryoneUserInfo());
+
+        return manager.resolveFile(uri, fileSystemOptions);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/LargeTarTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/LargeTarTestCase.java
new file mode 100644
index 0000000..e99c1a8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/LargeTarTestCase.java
@@ -0,0 +1,184 @@
+package org.apache.commons.vfs.provider.tar.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.apache.commons.compress.archivers.ArchiveStreamFactory;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.compressors.CompressorStreamFactory;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
+import org.apache.commons.compress.utils.IOUtils;
+import org.apache.commons.vfs.CacheStrategy;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.cache.SoftRefFilesCache;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+
+//@SuppressWarnings("nls")
+public class LargeTarTestCase extends TestCase {
+  private final static String baseDir = "target/test-classes/test-data/";
+
+  private DefaultFileSystemManager manager;
+  private final static String largeFilePath = baseDir;
+  private final static String largeFileName = "largefile";
+
+
+  public void setUp() throws Exception {
+    manager = new DefaultFileSystemManager();
+
+    manager.setFilesCache(new SoftRefFilesCache());
+    manager.setCacheStrategy(CacheStrategy.ON_RESOLVE);
+
+    manager.addProvider("file", new DefaultLocalFileProvider());
+    manager.addProvider("tgz", new TarFileProvider());
+    manager.addProvider("tar", new TarFileProvider());
+
+    createLargeFile(largeFilePath, largeFileName);
+  }
+
+  public void testLargeFile() throws Exception {
+    File realFile = new File(largeFilePath + largeFileName + ".tar.gz");
+
+    FileObject file = manager.resolveFile("tgz:file://" + realFile.getCanonicalPath() + "!/");
+
+    assertNotNull(file);
+    List files = Arrays.asList(file.getChildren());
+
+    assertNotNull(files);
+    assertEquals(1, files.size());
+    FileObject f = (FileObject) files.get(0);
+
+    assertTrue("Expected file not found: " + largeFileName + ".txt",
+        f.getName().getBaseName().equals(largeFileName + ".txt"));
+  }
+
+/*
+  public void testFileCheck() throws Exception {
+    String[] expectedFiles = {
+      "plugins.tsv",
+      "languages.tsv",
+      "browser_type.tsv",
+      "timezones.tsv",
+      "color_depth.tsv",
+      "resolution.tsv",
+      "connection_type.tsv",
+      "search_engines.tsv",
+      "javascript_version.tsv",
+      "operating_systems.tsv",
+      "country.tsv",
+      "browser.tsv"
+    };
+
+    fileCheck(expectedFiles, "tar:file://c:/temp/data/data/data-small.tar");
+  } */
+
+  protected void fileCheck(String[] expectedFiles, String tarFile) throws Exception {
+    assertNotNull(manager);
+    FileObject file = manager.resolveFile(tarFile);
+
+    assertNotNull(file);
+    List files = Arrays.asList(file.getChildren());
+
+    assertNotNull(files);
+    for(int i=0; i < expectedFiles.length; ++i) {
+      String expectedFile = expectedFiles[i];
+      assertTrue("Expected file not found: " + expectedFile, fileExists(expectedFile, files));
+    }
+  }
+
+  /**
+   * Search for the expected file in a given list, without using the full path
+   * @param expectedFile
+   * @param files
+   * @return
+   */
+  protected boolean fileExists(String expectedFile, List files) {
+    Iterator iter = files.iterator();
+    while (iter.hasNext()) {
+      FileObject file = (FileObject) iter.next();
+      if(file.getName().getBaseName().equals(expectedFile)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  protected boolean endsWith(String testString, String[] testList) {
+    for(int i=0; i < testList.length; ++i) {
+      String testItem = testList[i];
+      if(testString.endsWith(testItem)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  //@SuppressWarnings("unused")
+  protected void createLargeFile(String path, String name) throws Exception {
+    long _1K = 1024;
+    long _1M = 1024 * _1K;
+    long _256M = 256 * _1M;
+    long _512M = 512 * _1M;
+    long _1G = 1024 * _1M;
+
+    // File size of 3 GB
+    long fileSize = 3 * _1G;
+
+    File tarGzFile = new File(path + name + ".tar.gz");
+
+    if(!tarGzFile.exists()) {
+      System.out.println("This test is a bit slow. It needs to write a 3GB file to your hard drive");  
+
+      // Create archive
+      OutputStream outTarFileStream = new FileOutputStream(path + name + ".tar");
+
+      TarArchiveOutputStream outTarStream = (TarArchiveOutputStream)new ArchiveStreamFactory()
+      .createArchiveOutputStream(ArchiveStreamFactory.TAR, outTarFileStream);
+
+      // Create archive contents
+      TarArchiveEntry tarArchiveEntry = new TarArchiveEntry(name + ".txt");
+      tarArchiveEntry.setSize(fileSize);
+
+      outTarStream.putArchiveEntry(tarArchiveEntry);
+      for(long i = 0; i < fileSize; i++) {
+        outTarStream.write('a');
+      }
+
+      outTarStream.closeArchiveEntry();
+      outTarStream.close();
+
+      outTarFileStream.close();
+
+      // Create compressed archive
+      OutputStream outGzipFileStream = new FileOutputStream(path + name + ".tar.gz");
+
+      GzipCompressorOutputStream outGzipStream = (GzipCompressorOutputStream)new CompressorStreamFactory()
+      .createCompressorOutputStream(CompressorStreamFactory.GZIP, outGzipFileStream);
+
+      // Compress archive
+      InputStream inTarFileStream = new FileInputStream(path + name + ".tar");
+      // TODO: Change to a Piped Stream to conserve disk space
+      IOUtils.copy(inTarFileStream, outGzipStream);
+      inTarFileStream.close();
+
+      outGzipStream.close();
+      outGzipFileStream.close();
+
+      // Cleanup original tar
+      File tarFile = new File(path + name + ".tar");
+      if(tarFile.exists()) {
+        tarFile.delete();
+      }
+    }
+  }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTarTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTarTestCase.java
new file mode 100644
index 0000000..869f42d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTarTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for the Tar file system, using a tar file nested inside another tar file.
+ */
+public class NestedTarTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for nested tar files.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new NestedTarTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("tar", new TarFileProvider());
+        manager.addExtensionMap("tar", "tar");
+        manager.addMimeTypeMap("application/x-tar", "tar");
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        // Locate the base Tar file
+        final String tarFilePath = AbstractVfsTestCase.getTestResource("nested.tar").getAbsolutePath();
+        String uri = "tar:file:" + tarFilePath + "!/test.tar";
+        final FileObject tarFile = manager.resolveFile(uri);
+
+        // Now build the nested file system
+        final FileObject nestedFS = manager.createFileSystem(tarFile);
+        return nestedFS.resolveFile("/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTbz2TestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTbz2TestCase.java
new file mode 100644
index 0000000..0ac6f2c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTbz2TestCase.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for the Tar file system, using a tar file nested inside another tar file.
+ */
+public class NestedTbz2TestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for nested tar files.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new NestedTbz2TestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("tbz2", new TarFileProvider());
+        manager.addExtensionMap("tbz2", "tbz2");
+        manager.addProvider("tar", new TarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        // Locate the base Tar file
+        final String tarFilePath = AbstractVfsTestCase.getTestResource("nested.tbz2").getAbsolutePath();
+        String uri = "tbz2:file:" + tarFilePath + "!/test.tbz2";
+        final FileObject tarFile = manager.resolveFile(uri);
+
+        // Now build the nested file system
+        final FileObject nestedFS = manager.createFileSystem(tarFile);
+        return nestedFS.resolveFile("/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTgzTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTgzTestCase.java
new file mode 100644
index 0000000..9345a51
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/NestedTgzTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for the Tar file system, using a tar file nested inside another tar file.
+ */
+public class NestedTgzTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for nested tar files.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new NestedTgzTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("tgz", new TarFileProvider());
+        manager.addExtensionMap("tgz", "tgz");
+        manager.addProvider("tar", new TarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        // Locate the base Tar file
+        final String tarFilePath = AbstractVfsTestCase.getTestResource("nested.tgz").getAbsolutePath();
+        String uri = "tgz:file:" + tarFilePath + "!/test.tgz";
+        final FileObject tarFile = manager.resolveFile(uri);
+
+        // Now build the nested file system
+        final FileObject nestedFS = manager.createFileSystem(tarFile);
+        return nestedFS.resolveFile("/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TarProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TarProviderTestCase.java
new file mode 100644
index 0000000..123d6c1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TarProviderTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Tar file system.
+ */
+public class TarProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the tar file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new TarProviderTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        manager.addProvider("tar", new TarFileProvider());
+        manager.addMimeTypeMap("application/x-tar", "tar");
+    }
+
+    /**
+     * Returns the base folder for read tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File tarFile = AbstractVfsTestCase.getTestResource("test.tar");
+        final String uri = "tar:file:" + tarFile.getAbsolutePath() + "!/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/Tbz2ProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/Tbz2ProviderTestCase.java
new file mode 100644
index 0000000..d1ba1b8
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/Tbz2ProviderTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Tar file system.
+ */
+public class Tbz2ProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the tar file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new Tbz2ProviderTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        manager.addProvider("tbz2", new TarFileProvider());
+        manager.addProvider("tar", new TarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for read tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File tarFile = AbstractVfsTestCase.getTestResource("test.tbz2");
+        final String uri = "tbz2:file:" + tarFile.getAbsolutePath() + "!/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TgzProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TgzProviderTestCase.java
new file mode 100644
index 0000000..9a0b082
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/tar/test/TgzProviderTestCase.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.tar.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.tar.TarFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Tar file system.
+ */
+public class TgzProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the tar file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new TgzProviderTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        // manager.addProvider("tgz", new TgzFileProvider());
+        manager.addProvider("tgz", new TarFileProvider());
+        manager.addProvider("tar", new TarFileProvider());
+    }
+
+    /**
+     * Returns the base folder for read tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File tarFile = AbstractVfsTestCase.getTestResource("test.tgz");
+        final String uri = "tgz:file:" + tarFile.getAbsolutePath() + "!/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/temp/test/TemporaryProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/temp/test/TemporaryProviderTestCase.java
new file mode 100644
index 0000000..92964f9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/temp/test/TemporaryProviderTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.temp.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.temp.TemporaryFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Test cases for the tmp: file provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class TemporaryProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the tmp file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new TemporaryProviderTestCase());
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        final File baseDir = AbstractVfsTestCase.getTestDirectoryFile();
+        manager.addProvider("tmp", new TemporaryFileProvider(baseDir));
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        return manager.resolveFile("tmp:/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/GenericFileNameTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/GenericFileNameTestCase.java
new file mode 100644
index 0000000..fc9507d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/GenericFileNameTestCase.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.test;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.GenericFileName;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+
+/**
+ * Some GenericFileName test cases.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class GenericFileNameTestCase
+    extends AbstractVfsTestCase
+{
+    /**
+     * Tests parsing a URI into its parts.
+     */
+    public void testParseUri() throws Exception
+    {
+        URLFileNameParser urlParser = new URLFileNameParser(21);
+        // Simple name
+        GenericFileName name = (GenericFileName) urlParser.parseUri(null, null, "ftp://hostname/file");
+        assertEquals("ftp", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(21, name.getPort());
+        assertEquals(name.getDefaultPort(), name.getPort());
+        assertEquals("/file", name.getPath());
+        assertEquals("ftp://hostname/", name.getRootURI());
+        assertEquals("ftp://hostname/file", name.getURI());
+
+        // Name with port
+        name = (GenericFileName) urlParser.parseUri(null, null, "ftp://hostname:9090/file");
+        assertEquals("ftp", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(9090, name.getPort());
+        assertEquals("/file", name.getPath());
+        assertEquals("ftp://hostname:9090/", name.getRootURI());
+        assertEquals("ftp://hostname:9090/file", name.getURI());
+
+        // Name with no path
+        name = (GenericFileName) urlParser.parseUri(null, null, "ftp://hostname");
+        assertEquals("ftp", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(21, name.getPort());
+        assertEquals("/", name.getPath());
+        assertEquals("ftp://hostname/", name.getRootURI());
+        assertEquals("ftp://hostname/", name.getURI());
+
+        // Name with username
+        name = (GenericFileName) urlParser.parseUri(null, null, "ftp://user@hostname/file");
+        assertEquals("ftp", name.getScheme());
+        assertEquals("user", name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(21, name.getPort());
+        assertEquals("/file", name.getPath());
+        assertEquals("ftp://user@hostname/", name.getRootURI());
+        assertEquals("ftp://user@hostname/file", name.getURI());
+
+        // Name with username and password
+        name = (GenericFileName) urlParser.parseUri(null, null, "ftp://user:password@hostname/file");
+        assertEquals("ftp", name.getScheme());
+        assertEquals("user", name.getUserName());
+        assertEquals("password", name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(21, name.getPort());
+        assertEquals("/file", name.getPath());
+        assertEquals("ftp://user:password@hostname/", name.getRootURI());
+        assertEquals("ftp://user:password@hostname/file", name.getURI());
+
+        // Encoded username and password
+        name = (GenericFileName) urlParser.parseUri(null, null, "ftp://%75ser%3A:%40@hostname");
+        assertEquals("ftp", name.getScheme());
+        assertEquals("user:", name.getUserName());
+        assertEquals("@", name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(21, name.getPort());
+        assertEquals("/", name.getPath());
+        assertEquals("ftp://user%3a:%40@hostname/", name.getRootURI());
+        assertEquals("ftp://user%3a:%40@hostname/", name.getURI());
+    }
+
+    /**
+     * Tests error handling in URI parser.
+     */
+    public void testBadlyFormedUri() throws Exception
+    {
+        // Does not start with ftp://
+        testBadlyFormedUri("ftp:", "vfs.provider/missing-double-slashes.error");
+        testBadlyFormedUri("ftp:/", "vfs.provider/missing-double-slashes.error");
+        testBadlyFormedUri("ftp:a", "vfs.provider/missing-double-slashes.error");
+
+        // Missing hostname
+        testBadlyFormedUri("ftp://", "vfs.provider/missing-hostname.error");
+        testBadlyFormedUri("ftp://:21/file", "vfs.provider/missing-hostname.error");
+        testBadlyFormedUri("ftp:///file", "vfs.provider/missing-hostname.error");
+
+        // Empty port
+        testBadlyFormedUri("ftp://host:", "vfs.provider/missing-port.error");
+        testBadlyFormedUri("ftp://host:/file", "vfs.provider/missing-port.error");
+        testBadlyFormedUri("ftp://host:port/file", "vfs.provider/missing-port.error");
+
+        // Missing absolute path
+        testBadlyFormedUri("ftp://host:90a", "vfs.provider/missing-hostname-path-sep.error");
+        testBadlyFormedUri("ftp://host?a", "vfs.provider/missing-hostname-path-sep.error");
+    }
+
+    /**
+     * Tests that parsing a URI fails with the expected error.
+     */
+    private void testBadlyFormedUri(final String uri, final String errorMsg)
+    {
+        try
+        {
+            new URLFileNameParser(80).parseUri(null, null, uri);
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            assertSameMessage(errorMsg, uri, e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionProviderConfig.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionProviderConfig.java
new file mode 100644
index 0000000..d25eea4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionProviderConfig.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.test;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+
+/**
+ * A provider config that wraps another provider, to run the tests via
+ * junctions.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class JunctionProviderConfig
+    implements ProviderTestConfig
+{
+    private final ProviderTestConfig config;
+
+    public JunctionProviderConfig(final ProviderTestConfig config)
+    {
+        this.config = config;
+    }
+    
+    /**
+     * Returns a DefaultFileSystemManager instance (or subclass instance).
+     */
+    public DefaultFileSystemManager getDefaultFileSystemManager() {
+        return config.getDefaultFileSystemManager();
+    }
+
+    public FilesCache getFilesCache()
+    {
+        return config.getFilesCache();
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        config.prepare(manager);
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final FileObject baseFolder = config.getBaseTestFolder(manager);
+
+        // Create an empty file system, then link in the base folder
+        final FileSystem newFs = manager.createVirtualFileSystem("vfs:").getFileSystem();
+        final String junctionPoint = "/some/dir";
+        newFs.addJunction(junctionPoint, baseFolder);
+
+        return newFs.resolveFile(junctionPoint);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionTests.java
new file mode 100644
index 0000000..d82dda3
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/JunctionTests.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.test;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+
+import java.io.File;
+
+/**
+ * Additional junction test cases.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class JunctionTests
+    extends AbstractProviderTestCase
+{
+    private FileObject getBaseDir() throws FileSystemException
+    {
+        final File file = AbstractVfsTestCase.getTestDirectoryFile();
+        assertTrue(file.exists());
+        return getManager().toFileObject(file);
+    }
+
+    /**
+     * Checks nested junctions are not supported.
+     */
+    public void testNestedJunction() throws Exception
+    {
+        final FileSystem fs = getManager().createVirtualFileSystem("vfs:").getFileSystem();
+        final FileObject baseDir = getBaseDir();
+        fs.addJunction("/a", baseDir);
+
+        // Nested
+        try
+        {
+            fs.addJunction("/a/b", baseDir);
+            fail();
+        }
+        catch (final Exception e)
+        {
+            assertSameMessage("vfs.impl/nested-junction.error", "vfs:/a/b", e);
+        }
+
+        // At same point
+        try
+        {
+            fs.addJunction("/a", baseDir);
+            fail();
+        }
+        catch (final Exception e)
+        {
+            assertSameMessage("vfs.impl/nested-junction.error", "vfs:/a", e);
+        }
+    }
+
+    /**
+     * Checks ancestors are created when a junction is created.
+     */
+    public void testAncestors() throws Exception
+    {
+        final FileSystem fs = getManager().createVirtualFileSystem("vfs://").getFileSystem();
+        final FileObject baseDir = getBaseDir();
+
+        // Make sure the file at the junction point and its ancestors do not exist
+        FileObject file = fs.resolveFile("/a/b");
+        assertFalse(file.exists());
+        file = file.getParent();
+        assertFalse(file.exists());
+        file = file.getParent();
+        assertFalse(file.exists());
+
+        // Add the junction
+        fs.addJunction("/a/b", baseDir);
+
+        // Make sure the file at the junction point and its ancestors exist
+        file = fs.resolveFile("/a/b");
+        assertTrue("Does not exist", file.exists());
+        file = file.getParent();
+        assertTrue("Does not exist", file.exists());
+        file = file.getParent();
+        assertTrue("Does not exist", file.exists());
+    }
+
+    // Check that file @ junction point exists only when backing file exists
+    // Add 2 junctions with common parent
+    // Compare real and virtual files
+    // Events
+    // Remove junctions
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/VirtualProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/VirtualProviderTestCase.java
new file mode 100644
index 0000000..e4dadf5
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/test/VirtualProviderTestCase.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Test cases for the virtual file system provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class VirtualProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        final ProviderTestSuite testSuite = new ProviderTestSuite(new VirtualProviderTestCase());
+        testSuite.addTests(JunctionTests.class);
+        return testSuite;
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File baseDir = AbstractVfsTestCase.getTestDirectoryFile();
+        final FileObject baseFile = manager.toFileObject(baseDir);
+        return manager.createVirtualFileSystem(baseFile);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlHttpProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlHttpProviderTestCase.java
new file mode 100644
index 0000000..f3b4bfe
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlHttpProviderTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * Test cases for the generic provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlHttpProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new UrlHttpProviderTestCase());
+    }
+
+    /**
+     * Prepares the file system manager.  This implementation does nothing.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("http", new UrlFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+        throws Exception
+    {
+        final File baseDir = AbstractVfsTestCase.getTestDirectoryFile();
+        final URL url = baseDir.toURL();
+        return manager.resolveFile(url.toExternalForm());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderHttpTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderHttpTestCase.java
new file mode 100644
index 0000000..9bead71
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderHttpTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url.test;
+
+import junit.framework.Test;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Test cases for HTTP with the default provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlProviderHttpTestCase
+    extends AbstractProviderTestConfig
+{
+    private static final String TEST_URI = "test.http.uri";
+
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            return new ProviderTestSuite(new UrlProviderTestCase());
+        }
+        else
+        {
+            return notConfigured(UrlProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("http", new UrlFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+        throws Exception
+    {
+        final String uri = System.getProperty(TEST_URI);
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderTestCase.java
new file mode 100644
index 0000000..3d4ec3b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/url/test/UrlProviderTestCase.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.url.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+import java.net.URL;
+
+/**
+ * Test cases for the generic provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new UrlProviderTestCase());
+    }
+
+    /**
+     * Prepares the file system manager.  This implementation does nothing.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("file", new UrlFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+        throws Exception
+    {
+        final File baseDir = AbstractVfsTestCase.getTestDirectoryFile();
+        final URL url = baseDir.toURL();
+        return manager.resolveFile(url.toExternalForm());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestCase.java
new file mode 100644
index 0000000..0f5eb7f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestCase.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav.test;
+
+import junit.framework.Test;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.temp.TemporaryFileProvider;
+import org.apache.commons.vfs.provider.webdav.WebdavFileProvider;
+import org.apache.commons.vfs.provider.webdav.WebdavFileSystemConfigBuilder;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Test cases for the WebDAV provider.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class WebdavProviderTestCase
+    extends AbstractProviderTestConfig
+{
+    private static final String TEST_URI = "test.webdav.uri";
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            ProviderTestSuite suite = new WebdavProviderTestSuite(new WebdavProviderTestCase());
+            suite.addTests(WebdavVersioningTests.class);
+            return suite;
+        }
+        else
+        {
+            return notConfigured(WebdavProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("webdav", new WebdavFileProvider());
+        manager.addProvider("tmp", new TemporaryFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager)
+        throws Exception
+    {
+        WebdavFileSystemConfigBuilder builder =
+            (WebdavFileSystemConfigBuilder)manager.getFileSystemConfigBuilder("webdav");
+        final String uri = System.getProperty(TEST_URI);
+        FileSystemOptions opts = new FileSystemOptions();
+        builder.setRootURI(opts, uri);
+        return manager.resolveFile(uri, opts);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestSuite.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestSuite.java
new file mode 100644
index 0000000..b61b6a9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavProviderTestSuite.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav.test;
+
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderCacheStrategyTests;
+import org.apache.commons.vfs.test.UriTests;
+import org.apache.commons.vfs.test.NamingTests;
+import org.apache.commons.vfs.test.ContentTests;
+import org.apache.commons.vfs.test.ProviderReadTests;
+import org.apache.commons.vfs.test.ProviderRandomReadTests;
+import org.apache.commons.vfs.test.ProviderWriteTests;
+import org.apache.commons.vfs.test.ProviderWriteAppendTests;
+import org.apache.commons.vfs.test.ProviderRandomReadWriteTests;
+import org.apache.commons.vfs.test.ProviderRenameTests;
+import org.apache.commons.vfs.test.ProviderDeleteTests;
+import org.apache.commons.vfs.test.LastModifiedTests;
+import org.apache.commons.vfs.test.UrlTests;
+import org.apache.commons.vfs.test.UrlStructureTests;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * The suite of tests for a file system.
+ *
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ * @version $Id$
+ */
+public class WebdavProviderTestSuite extends ProviderTestSuite
+{
+    /**
+     * Adds the tests for a file system to this suite.
+     */
+    public WebdavProviderTestSuite(final ProviderTestConfig providerConfig) throws Exception
+    {
+        this(providerConfig, "", false, false);
+    }
+
+    /**
+     * Adds the tests for a file system to this suite. Provider has an empty directory.
+     */
+    public WebdavProviderTestSuite(final ProviderTestConfig providerConfig,
+                             final boolean addEmptyDir) throws Exception
+    {
+        this(providerConfig, "", false, addEmptyDir);
+    }
+
+
+
+    protected WebdavProviderTestSuite(final ProviderTestConfig providerConfig,
+                                final String prefix,
+                                final boolean nested,
+                                final boolean addEmptyDir)
+        throws Exception
+    {
+        super(providerConfig, prefix, nested, addEmptyDir);
+    }
+
+    /**
+     * Adds base tests - excludes the nested test cases.
+     */
+    protected void addBaseTests() throws Exception
+    {
+        addTests(ProviderCacheStrategyTests.class);
+        addTests(UriTests.class);
+        addTests(NamingTests.class);
+        addTests(ContentTests.class);
+        addTests(ProviderReadTests.class);
+        addTests(ProviderRandomReadTests.class);
+        addTests(ProviderWriteTests.class);
+        addTests(ProviderWriteAppendTests.class);
+        addTests(ProviderRandomReadWriteTests.class);
+        addTests(ProviderRenameTests.class);
+        addTests(ProviderDeleteTests.class);
+        addTests(LastModifiedTests.class);
+        addTests(UrlTests.class);
+        addTests(UrlStructureTests.class);
+        // The class loader test requires the classes be uploaded to the webdav repo.
+        //addTests(VfsClassLoaderTests.class);
+    }
+}
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavVersioningTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavVersioningTests.java
new file mode 100644
index 0000000..0d61594
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/webdav/test/WebdavVersioningTests.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.webdav.test;
+
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.provider.webdav.WebdavFileSystemConfigBuilder;
+import org.apache.commons.vfs.provider.URLFileName;
+import org.apache.commons.vfs.test.AbstractProviderTestCase;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.VersionControlledResource;
+
+/**
+ * Test to verify Webdav Versioning support
+ */
+public class WebdavVersioningTests extends AbstractProviderTestCase
+{
+    /**
+     *
+     */
+    public void testVersioning() throws Exception
+    {
+        FileObject scratchFolder = createScratchFolder();
+        FileSystemOptions opts = scratchFolder.getFileSystem().getFileSystemOptions();
+        WebdavFileSystemConfigBuilder builder =
+            (WebdavFileSystemConfigBuilder)getManager().getFileSystemConfigBuilder("webdav");
+        builder.setVersioning(opts, true);
+        FileObject file = getManager().resolveFile(scratchFolder, "file1.txt", opts);
+        FileSystemOptions newOpts = file.getFileSystem().getFileSystemOptions();
+        assertTrue(opts == newOpts);
+        assertTrue(builder.isVersioning(newOpts));
+        assertTrue(!file.exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+        assertEquals(0, file.getContent().getSize());
+        assertFalse(file.isHidden());
+        assertTrue(file.isReadable());
+        assertTrue(file.isWriteable());
+        Map map = file.getContent().getAttributes();
+        String name = ((URLFileName)file.getName()).getUserName();
+        assertTrue(map.containsKey(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        if (name != null)
+        {
+            assertEquals(name, map.get(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        }
+        assertTrue(map.containsKey(VersionControlledResource.CHECKED_IN.toString()));
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final String contentAppend = content + content;
+
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+        assertSameContent(content, file);
+        map = file.getContent().getAttributes();
+        assertTrue(map.containsKey(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        if (name != null)
+        {
+            assertEquals(name, map.get(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        }
+        assertTrue(map.containsKey(VersionControlledResource.CHECKED_IN.toString()));
+        builder.setVersioning(opts, false);
+    }
+    /**
+     *
+     */
+    public void testVersioningWithCreator() throws Exception
+    {
+        FileObject scratchFolder = createScratchFolder();
+        FileSystemOptions opts = scratchFolder.getFileSystem().getFileSystemOptions();
+        WebdavFileSystemConfigBuilder builder =
+            (WebdavFileSystemConfigBuilder)getManager().getFileSystemConfigBuilder("webdav");
+        builder.setVersioning(opts, true);
+        builder.setCreatorName(opts, "testUser");
+        FileObject file = getManager().resolveFile(scratchFolder, "file1.txt", opts);
+        FileSystemOptions newOpts = file.getFileSystem().getFileSystemOptions();
+        assertTrue(opts == newOpts);
+        assertTrue(builder.isVersioning(newOpts));
+        assertTrue(!file.exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+        assertEquals(0, file.getContent().getSize());
+        assertFalse(file.isHidden());
+        assertTrue(file.isReadable());
+        assertTrue(file.isWriteable());
+        Map map = file.getContent().getAttributes();
+        String name = ((URLFileName)file.getName()).getUserName();
+        assertTrue(map.containsKey(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        assertEquals(map.get(DeltaVConstants.CREATOR_DISPLAYNAME.toString()),"testUser");
+        if (name != null)
+        {
+            assertTrue(map.containsKey(DeltaVConstants.COMMENT.toString()));
+            assertEquals("Modified by user " + name, map.get(DeltaVConstants.COMMENT.toString()));
+        }
+        assertTrue(map.containsKey(VersionControlledResource.CHECKED_IN.toString()));
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final String contentAppend = content + content;
+
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+        assertSameContent(content, file);
+        map = file.getContent().getAttributes();
+        assertTrue(map.containsKey(DeltaVConstants.CREATOR_DISPLAYNAME.toString()));
+        assertEquals(map.get(DeltaVConstants.CREATOR_DISPLAYNAME.toString()),"testUser");
+        if (name != null)
+        {
+            assertTrue(map.containsKey(DeltaVConstants.COMMENT.toString()));
+            assertEquals("Modified by user " + name, map.get(DeltaVConstants.COMMENT.toString()));
+        }
+        assertTrue(map.containsKey(VersionControlledResource.CHECKED_IN.toString()));
+        builder.setVersioning(opts, false);
+        builder.setCreatorName(opts, null);
+    }
+        /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/NestedZipTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/NestedZipTestCase.java
new file mode 100644
index 0000000..ae67473
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/NestedZipTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.zip.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.zip.ZipFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for the Zip file system, using a zip file nested inside another zip file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class NestedZipTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for nested zip files.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new NestedZipTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("zip", new ZipFileProvider());
+        manager.addExtensionMap("zip", "zip");
+        manager.addMimeTypeMap("application/zip", "zip");
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        // Locate the base Zip file
+        final String zipFilePath = AbstractVfsTestCase.getTestResource("nested.zip").getAbsolutePath();
+        String uri = "zip:file:" + zipFilePath + "!/test.zip";
+        final FileObject zipFile = manager.resolveFile(uri);
+
+        // Now build the nested file system
+        final FileObject nestedFS = manager.createFileSystem(zipFile);
+        return nestedFS.resolveFile("/");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/ZipProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/ZipProviderTestCase.java
new file mode 100644
index 0000000..687a93f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/provider/zip/test/ZipProviderTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.zip.test;
+
+import junit.framework.Test;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.zip.ZipFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+import java.io.File;
+
+/**
+ * Tests for the Zip file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class ZipProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    /**
+     * Creates the test suite for the zip file system.
+     */
+    public static Test suite() throws Exception
+    {
+        return new ProviderTestSuite(new ZipProviderTestCase(), true);
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager) throws Exception
+    {
+        manager.addProvider("zip", new ZipFileProvider());
+        manager.addExtensionMap("zip", "zip");
+        manager.addMimeTypeMap("application/zip", "zip");
+    }
+
+    /**
+     * Returns the base folder for read tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final File zipFile = AbstractVfsTestCase.getTestResource("test.zip");
+        final String uri = "zip:file:" + zipFile.getAbsolutePath() + "!/";
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestCase.java
new file mode 100644
index 0000000..e026f9f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestCase.java
@@ -0,0 +1,394 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URLConnection;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+
+/**
+ * File system test cases, which verifies the structure and naming
+ * functionality.
+ * <p/>
+ * Works from a base folder, and assumes a particular structure under
+ * that base folder.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractProviderTestCase
+    extends AbstractVfsTestCase
+{
+    private FileObject baseFolder;
+    private FileObject readFolder;
+    private FileObject writeFolder;
+    private DefaultFileSystemManager manager;
+    private ProviderTestConfig providerConfig;
+    private Method method;
+    private boolean addEmptyDir;
+
+    // Expected contents of "file1.txt"
+    public static final String FILE1_CONTENT = "This is a test file.";
+
+    // Expected contents of test files
+    public static final String TEST_FILE_CONTENT = "A test file.";
+
+    /**
+     * Sets the test method.
+     */
+    public void setMethod(final Method method)
+    {
+        this.method = method;
+    }
+
+    /**
+     * Configures this test.
+     */
+    public void setConfig(final DefaultFileSystemManager manager,
+                          final ProviderTestConfig providerConfig,
+                          final FileObject baseFolder,
+                          final FileObject readFolder,
+                          final FileObject writeFolder)
+    {
+        this.manager = manager;
+        this.providerConfig = providerConfig;
+        this.baseFolder = baseFolder;
+        this.readFolder = readFolder;
+        this.writeFolder = writeFolder;
+    }
+
+    /**
+     * Returns the file system manager used by this test.
+     */
+    protected DefaultFileSystemManager getManager()
+    {
+        return manager;
+    }
+
+    /**
+     * creates a new uninitialized file system manager
+     * @throws Exception
+     */
+    protected DefaultFileSystemManager createManager() throws Exception
+    {
+        DefaultFileSystemManager fs = getProviderConfig().getDefaultFileSystemManager();
+        fs.setFilesCache(getProviderConfig().getFilesCache());
+        getProviderConfig().prepare(fs);
+        if (!fs.hasProvider("file"))
+        {
+            fs.addProvider("file", new DefaultLocalFileProvider());
+        }
+        return fs;
+    }
+
+    /**
+     * some provider config do some post-initialization in getBaseTestFolder.
+     * This is a hack to allow access to this code for <code>createManager</code>
+     */
+    public FileObject getBaseTestFolder(FileSystemManager fs) throws Exception
+    {
+        return providerConfig.getBaseTestFolder(fs);
+    }
+
+    /**
+     * Returns the base test folder.  This is the parent of both the read
+     * test and write test folders.
+     */
+    public FileObject getBaseFolder()
+    {
+        return baseFolder;
+    }
+
+    /**
+     * get the provider configuration
+     */
+    public ProviderTestConfig getProviderConfig()
+    {
+        return providerConfig;
+    }
+
+    /**
+     * Returns the read test folder.
+     */
+    protected FileObject getReadFolder()
+    {
+        return readFolder;
+    }
+
+    /**
+     * Returns the write test folder.
+     */
+    protected FileObject getWriteFolder()
+    {
+        return writeFolder;
+    }
+
+    /**
+     * Sets the write test folder.
+     * @param folder
+     */
+    protected void setWriteFolder(FileObject folder)
+    {
+        writeFolder = folder;
+    }
+
+    /**
+     * Returns the capabilities required by the tests of this test case.  The
+     * tests are not run if the provider being tested does not support all
+     * the required capabilities.  Return null or an empty array to always
+     * run the tests.
+     * <p/>
+     * <p>This implementation returns null.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return null;
+    }
+
+    /**
+     * Runs the test.  This implementation short-circuits the test if the
+     * provider being tested does not have the capabilities required by this
+     * test.
+     *
+     * @todo Handle negative caps as well - ie, only run a test if the provider does not have certain caps.
+     * @todo Figure out how to remove the test from the TestResult if the test is skipped.
+     */
+    protected void runTest() throws Throwable
+    {
+        // Check the capabilities
+        final Capability[] caps = getRequiredCaps();
+        if (caps != null)
+        {
+            for (int i = 0; i < caps.length; i++)
+            {
+                final Capability cap = caps[i];
+                FileSystem fs = readFolder.getFileSystem();
+                String name = fs.getClass().getName();
+                int index = name.lastIndexOf('.');
+                String fsName = (index > 0) ? name.substring(index + 1) : name;
+                if (!fs.hasCapability(cap))
+                {
+                    System.out.println("skipping " + getName() + " because " +
+                        fsName + " does not have capability " + cap);
+                    return;
+                }
+            }
+        }
+
+        // Provider has all the capabilities - execute the test
+        if (method != null)
+        {
+            try
+            {
+                method.invoke(this, (Object[]) null);
+            }
+            catch (final InvocationTargetException e)
+            {
+                throw e.getTargetException();
+            }
+        }
+        else
+        {
+            super.runTest();
+        }
+
+        if (((AbstractFileSystem) readFolder.getFileSystem()).isOpen())
+        {
+            String name = "unknown";
+            if (method != null)
+            {
+                name = method.getName();
+            }
+
+            throw new IllegalStateException(getClass().getName() + ": filesystem has open streams after: " + name);
+        }
+    }
+
+    /**
+     * Asserts that the content of a file is the same as expected. Checks the
+     * length reported by getContentLength() is correct, then reads the content
+     * as a byte stream and compares the result with the expected content.
+     * Assumes files are encoded using UTF-8.
+     */
+    protected void assertSameURLContent(final String expected,
+                                        final URLConnection connection)
+        throws Exception
+    {
+        // Get file content as a binary stream
+        final byte[] expectedBin = expected.getBytes("utf-8");
+
+        // Check lengths
+        assertEquals("same content length", expectedBin.length, connection.getContentLength());
+
+        // Read content into byte array
+        final InputStream instr = connection.getInputStream();
+        final ByteArrayOutputStream outstr;
+        try
+        {
+            outstr = new ByteArrayOutputStream();
+            final byte[] buffer = new byte[256];
+            int nread = 0;
+            while (nread >= 0)
+            {
+                outstr.write(buffer, 0, nread);
+                nread = instr.read(buffer);
+            }
+        }
+        finally
+        {
+            instr.close();
+        }
+
+        // Compare
+        assertTrue("same binary content", Arrays.equals(expectedBin, outstr.toByteArray()));
+    }
+
+    /**
+     * Asserts that the content of a file is the same as expected. Checks the
+     * length reported by getSize() is correct, then reads the content as
+     * a byte stream and compares the result with the expected content.
+     * Assumes files are encoded using UTF-8.
+     */
+    protected void assertSameContent(final String expected,
+                                     final FileObject file)
+        throws Exception
+    {
+        // Check the file exists, and is a file
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+
+        // Get file content as a binary stream
+        final byte[] expectedBin = expected.getBytes("utf-8");
+
+        // Check lengths
+        final FileContent content = file.getContent();
+        assertEquals("same content length", expectedBin.length, content.getSize());
+
+        // Read content into byte array
+        final InputStream instr = content.getInputStream();
+        final ByteArrayOutputStream outstr;
+        try
+        {
+            outstr = new ByteArrayOutputStream(expectedBin.length);
+            final byte[] buffer = new byte[256];
+            int nread = 0;
+            while (nread >= 0)
+            {
+                outstr.write(buffer, 0, nread);
+                nread = instr.read(buffer);
+            }
+        }
+        finally
+        {
+            instr.close();
+        }
+
+        // Compare
+        assertTrue("same binary content", Arrays.equals(expectedBin, outstr.toByteArray()));
+    }
+
+    /**
+     * Builds the expected structure of the read tests folder.
+     */
+    protected FileInfo buildExpectedStructure() throws FileSystemException
+    {
+        // Build the expected structure
+        final FileInfo base = new FileInfo(getReadFolder().getName().getBaseName(), FileType.FOLDER);
+        base.addFile("file1.txt", FILE1_CONTENT);
+        // file%.txt - test out encoding
+        base.addFile("file%25.txt", FILE1_CONTENT);
+
+        // file?test.txt - test out encoding (test.txt is not the queryString)
+        // as we do not know if the current file provider we need to
+        // ask it to normalize the name
+        // todo: move this into the FileInfo class to do it generally?
+        /* webdav-bug?: didnt manage to get the "?" correctly through webdavlib
+        FileSystemManager fsm = getReadFolder().getFileSystem().getFileSystemManager();
+        FileName fn = fsm.resolveName(getReadFolder().getName(), "file%3ftest.txt");
+        String baseName = fn.getBaseName();
+        base.addFile(baseName, FILE1_CONTENT);
+        */
+        base.addFile("file space.txt", FILE1_CONTENT);
+
+        base.addFile("empty.txt", "");
+        if (addEmptyDir)
+        {
+            base.addFolder("emptydir");
+        }
+
+        final FileInfo dir = base.addFolder("dir1");
+        dir.addFile("file1.txt", TEST_FILE_CONTENT);
+        dir.addFile("file2.txt", TEST_FILE_CONTENT);
+        dir.addFile("file3.txt", TEST_FILE_CONTENT);
+
+        final FileInfo subdir1 = dir.addFolder("subdir1");
+        subdir1.addFile("file1.txt", TEST_FILE_CONTENT);
+        subdir1.addFile("file2.txt", TEST_FILE_CONTENT);
+        subdir1.addFile("file3.txt", TEST_FILE_CONTENT);
+
+        final FileInfo subdir2 = dir.addFolder("subdir2");
+        subdir2.addFile("file1.txt", TEST_FILE_CONTENT);
+        subdir2.addFile("file2.txt", TEST_FILE_CONTENT);
+        subdir2.addFile("file3.txt", TEST_FILE_CONTENT);
+
+        final FileInfo subdir3 = dir.addFolder("subdir3");
+        subdir3.addFile("file1.txt", TEST_FILE_CONTENT);
+        subdir3.addFile("file2.txt", TEST_FILE_CONTENT);
+        subdir3.addFile("file3.txt", TEST_FILE_CONTENT);
+
+        return base;
+    }
+
+    protected void addEmptyDir(boolean addEmptyDir)
+    {
+        this.addEmptyDir = addEmptyDir;
+    }
+
+    protected static Test notConfigured(Class testClass)
+    {
+        return warning(testClass + " is not configured for tests, skipping");
+    }
+
+    private static Test warning(final String message)
+    {
+        return new TestCase("warning")
+        {
+            protected void runTest()
+            {
+                  System.out.println(message);
+               }
+           };
+       }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestConfig.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestConfig.java
new file mode 100644
index 0000000..746086a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractProviderTestConfig.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.cache.SoftRefFilesCache;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+
+/**
+ * A partial {@link org.apache.commons.vfs.test.ProviderTestConfig} implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public abstract class AbstractProviderTestConfig extends AbstractProviderTestCase
+    implements ProviderTestConfig
+{
+    private FilesCache cache = null;
+    
+    /**
+     * Returns a DefaultFileSystemManager instance (or subclass instance).
+     */
+    public DefaultFileSystemManager getDefaultFileSystemManager() {
+        return new DefaultFileSystemManager();
+    }
+
+    /**
+     * Prepares the file system manager.  This implementation does nothing.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+    }
+
+    public FilesCache getFilesCache()
+    {
+        if (cache == null)
+        {
+            // cache = new DefaultFilesCache();
+            cache = new SoftRefFilesCache();
+        }
+
+        return cache;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractTestSuite.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractTestSuite.java
new file mode 100644
index 0000000..70b6f8f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/AbstractTestSuite.java
@@ -0,0 +1,357 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.impl.DefaultFileReplicator;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.impl.PrivilegedFileReplicator;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+/**
+ * The suite of tests for a file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Id$
+ */
+public abstract class AbstractTestSuite
+    extends TestSetup
+{
+    private final ProviderTestConfig providerConfig;
+    private final String prefix;
+    private TestSuite testSuite;
+
+    private FileObject baseFolder;
+    private FileObject readFolder;
+    private FileObject writeFolder;
+    private DefaultFileSystemManager manager;
+    private File tempDir;
+
+    private Thread[] startThreadSnapshot;
+    private Thread[] endThreadSnapshot;
+    private boolean addEmptyDir;
+
+    /**
+     * Adds the tests for a file system to this suite.
+     */
+    public AbstractTestSuite(final ProviderTestConfig providerConfig) throws Exception
+    {
+        this(providerConfig, "", false, false);
+    }
+
+    protected AbstractTestSuite(final ProviderTestConfig providerConfig,
+                                final String prefix,
+                                final boolean nested) throws Exception
+    {
+        this(providerConfig, prefix, nested, false);
+    }
+
+
+    protected AbstractTestSuite(final ProviderTestConfig providerConfig,
+                                final String prefix,
+                                final boolean nested,
+                                final boolean addEmptyDir)
+        throws Exception
+    {
+        super(new TestSuite());
+        testSuite = (TestSuite) fTest;
+        this.providerConfig = providerConfig;
+        this.prefix = prefix;
+        this.addEmptyDir = addEmptyDir;
+        addBaseTests();
+        if (!nested)
+        {
+            // Add nested tests
+            // TODO - move nested jar and zip tests here
+            // TODO - enable this again
+            //testSuite.addTest( new ProviderTestSuite( new JunctionProviderConfig( providerConfig ), "junction.", true ));
+        }
+    }
+
+    /**
+     * Adds base tests - excludes the nested test cases.
+     */
+    protected void addBaseTests() throws Exception
+    {
+    }
+
+    /**
+     * Adds the tests from a class to this suite.  The supplied class must be
+     * a subclass of {@link AbstractProviderTestCase} and have a public a
+     * no-args constructor.  This method creates an instance of the supplied
+     * class for each public 'testNnnn' method provided by the class.
+     */
+    public void addTests(final Class testClass) throws Exception
+    {
+        // Verify the class
+        if (!AbstractProviderTestCase.class.isAssignableFrom(testClass))
+        {
+            throw new Exception("Test class " + testClass.getName() + " is not assignable to " + AbstractProviderTestCase.class.getName());
+        }
+
+        // Locate the test methods
+        final Method[] methods = testClass.getMethods();
+        for (int i = 0; i < methods.length; i++)
+        {
+            final Method method = methods[i];
+            if (!method.getName().startsWith("test")
+                || Modifier.isStatic(method.getModifiers())
+                || method.getReturnType() != Void.TYPE
+                || method.getParameterTypes().length != 0)
+            {
+                continue;
+            }
+
+            // Create instance
+            final AbstractProviderTestCase testCase = (AbstractProviderTestCase) testClass.newInstance();
+            testCase.setMethod(method);
+            testCase.setName(prefix + method.getName());
+            testCase.addEmptyDir(this.addEmptyDir);
+            testSuite.addTest(testCase);
+        }
+    }
+
+    protected void setUp() throws Exception
+    {
+        startThreadSnapshot = createThreadSnapshot();
+
+        // Locate the temp directory, and clean it up
+        tempDir = AbstractVfsTestCase.getTestDirectory("temp");
+        checkTempDir("Temp dir not empty before test");
+
+        // Create the file system manager
+        manager = providerConfig.getDefaultFileSystemManager();
+        manager.setFilesCache(providerConfig.getFilesCache());
+
+        final DefaultFileReplicator replicator = new DefaultFileReplicator(tempDir);
+        manager.setReplicator(new PrivilegedFileReplicator(replicator));
+        manager.setTemporaryFileStore(replicator);
+
+        providerConfig.prepare(manager);
+
+        if (!manager.hasProvider("file"))
+        {
+            manager.addProvider("file", new DefaultLocalFileProvider());
+        }
+
+        manager.init();
+
+        // Locate the base folders
+        baseFolder = providerConfig.getBaseTestFolder(manager);
+        readFolder = baseFolder.resolveFile("read-tests");
+        writeFolder = baseFolder.resolveFile("write-tests");
+
+        // Make some assumptions about the read folder
+        assertTrue("Folder does not exist: " + readFolder, readFolder.exists());
+        assertFalse(readFolder.getName().getPath().equals(FileName.ROOT_PATH));
+
+        // Configure the tests
+        final Enumeration tests = testSuite.tests();
+        while (tests.hasMoreElements())
+        {
+            final Test test = (Test) tests.nextElement();
+            if (test instanceof AbstractProviderTestCase)
+            {
+                final AbstractProviderTestCase providerTestCase = (AbstractProviderTestCase) test;
+                providerTestCase.setConfig(manager, providerConfig, baseFolder, readFolder, writeFolder);
+            }
+        }
+    }
+
+    protected void tearDown() throws Exception
+    {
+        readFolder.close();
+        writeFolder.close();
+        baseFolder.close();
+
+        readFolder = null;
+        writeFolder = null;
+        baseFolder = null;
+        testSuite = null;
+        fTest = null;
+
+        // force the SoftRefFilesChache to free all files
+        System.err.println(".");
+        System.gc();
+        Thread.sleep(1000);
+        System.err.println(".");
+        System.gc();
+        Thread.sleep(1000);
+        System.err.println(".");
+        System.gc();
+        Thread.sleep(1000);
+        System.err.println(".");
+        System.gc();
+        Thread.sleep(1000);
+
+        manager.freeUnusedResources();
+        endThreadSnapshot = createThreadSnapshot();
+
+        Thread[] diffThreadSnapshot = diffThreadSnapshot(startThreadSnapshot, endThreadSnapshot);
+        if (diffThreadSnapshot.length > 0)
+        {
+            String message = dumpThreadSnapshot(diffThreadSnapshot);
+            /*
+            if (providerConfig.checkCleanThreadState())
+            {
+                // close the manager to do a "not thread safe" release of all resources
+                // and allow the vm to shutdown
+                manager.close();
+                fail(message);
+            }
+            else
+            {
+            */
+            System.out.println(message);
+            // }
+        }
+        // System.in.read();
+
+        manager.close();
+
+        // Make sure temp directory is empty or gone
+        checkTempDir("Temp dir not empty after test");
+    }
+
+    /**
+     * Asserts that the temp dir is empty or gone.
+     */
+    private void checkTempDir(final String assertMsg)
+    {
+        if (tempDir.exists())
+        {
+            assertTrue(assertMsg + " (" + tempDir.getAbsolutePath() + ")", tempDir.isDirectory() && tempDir.list().length == 0);
+        }
+    }
+
+    private String dumpThreadSnapshot(Thread[] threadSnapshot)
+    {
+        StringBuffer sb = new StringBuffer(256);
+        sb.append("created threads still running:\n");
+
+        Field threadTargetField = null;
+        try
+        {
+            threadTargetField = Thread.class.getDeclaredField("target");
+            threadTargetField.setAccessible(true);
+        }
+        catch (NoSuchFieldException e)
+        {
+            // ignored
+        }
+
+        for (int iter = 0; iter < threadSnapshot.length; iter++)
+        {
+            Thread thread = threadSnapshot[iter];
+            if (thread == null)
+            {
+                continue;
+            }
+
+            sb.append("#");
+            sb.append(iter + 1);
+            sb.append(": ");
+            sb.append(thread.getThreadGroup().getName());
+            sb.append("\t");
+            sb.append(thread.getName());
+            sb.append("\t");
+            if (thread.isDaemon())
+            {
+                sb.append("daemon");
+            }
+            else
+            {
+                sb.append("not_a_daemon");
+            }
+
+            if (threadTargetField != null)
+            {
+                sb.append("\t");
+                try
+                {
+                    Object threadTarget = threadTargetField.get(thread);
+                    if (threadTarget != null)
+                    {
+                        sb.append(threadTarget.getClass());
+                    }
+                    else
+                    {
+                        sb.append("null");
+                    }
+                }
+                catch (IllegalAccessException e)
+                {
+                    sb.append("unknown class");
+                }
+            }
+
+            sb.append("\n");
+        }
+
+        return sb.toString();
+    }
+
+    private Thread[] diffThreadSnapshot(Thread[] startThreadSnapshot, Thread[] endThreadSnapshot)
+    {
+        List diff = new ArrayList(10);
+
+        nextEnd: for (int iterEnd = 0; iterEnd < endThreadSnapshot.length; iterEnd++)
+        {
+            nextStart: for (int iterStart = 0; iterStart < startThreadSnapshot.length; iterStart++)
+            {
+                if (startThreadSnapshot[iterStart] == endThreadSnapshot[iterEnd])
+                {
+                    continue nextEnd;
+                }
+            }
+
+            diff.add(endThreadSnapshot[iterEnd]);
+        }
+
+        Thread ret[] = new Thread[diff.size()];
+        diff.toArray(ret);
+        return ret;
+    }
+
+    private Thread[] createThreadSnapshot()
+    {
+        ThreadGroup tg = Thread.currentThread().getThreadGroup();
+        while (tg.getParent() != null)
+        {
+            tg = tg.getParent();
+        }
+
+        Thread snapshot[] = new Thread[200];
+        tg.enumerate(snapshot, true);
+
+        return snapshot;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/CacheTestSuite.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/CacheTestSuite.java
new file mode 100644
index 0000000..a318b9c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/CacheTestSuite.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+
+/**
+ * The suite of tests for a file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Id$
+ */
+public class CacheTestSuite
+    extends AbstractTestSuite
+{
+    /**
+     * Adds the tests for a file system to this suite.
+     */
+    public CacheTestSuite(final ProviderTestConfig providerConfig) throws Exception
+    {
+        this(providerConfig, "", false);
+    }
+
+    protected CacheTestSuite(final ProviderTestConfig providerConfig,
+                             final String prefix,
+                             final boolean nested)
+        throws Exception
+    {
+        super(providerConfig, prefix, nested);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ContentTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ContentTests.java
new file mode 100644
index 0000000..63df499
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ContentTests.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+
+import java.io.InputStream;
+import java.util.Iterator;
+
+/**
+ * Test cases for reading file content.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class ContentTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Asserts that every expected file exists, and has the expected content.
+     */
+    public void testAllContent() throws Exception
+    {
+        final FileInfo baseInfo = buildExpectedStructure();
+        final FileObject baseFolder = getReadFolder();
+
+        assertSameContent(baseInfo, baseFolder);
+    }
+
+    /**
+     * Asserts every file in a folder exists and has the expected content.
+     */
+    private void assertSameContent(final FileInfo expected,
+                                   final FileObject folder) throws Exception
+    {
+        for (Iterator iterator = expected.children.values().iterator(); iterator.hasNext();)
+        {
+            final FileInfo fileInfo = (FileInfo) iterator.next();
+            final FileObject child = folder.resolveFile(fileInfo.baseName, NameScope.CHILD);
+
+            assertTrue(child.getName().toString(), child.exists());
+            if (fileInfo.type == FileType.FILE)
+            {
+                assertSameContent(fileInfo.content, child);
+            }
+            else
+            {
+                assertSameContent(fileInfo, child);
+            }
+        }
+    }
+
+    /**
+     * Tests existence determination.
+     */
+    public void testExists() throws Exception
+    {
+        // Test a file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertTrue("file exists", file.exists());
+        assertTrue("file exists", file.getType() != FileType.IMAGINARY);
+
+        // Test a folder
+        file = getReadFolder().resolveFile("dir1");
+        assertTrue("folder exists", file.exists());
+        assertTrue("folder exists", file.getType() != FileType.IMAGINARY);
+
+        // Test an unknown file
+        file = getReadFolder().resolveFile("unknown-child");
+        assertTrue("unknown file does not exist", !file.exists());
+        assertTrue("unknown file does not exist",
+            file.getType() == FileType.IMAGINARY);
+
+        // Test an unknown file in an unknown folder
+        file = getReadFolder().resolveFile("unknown-folder/unknown-child");
+        assertTrue("unknown file does not exist", !file.exists());
+        assertTrue("unknown file does not exist",
+            file.getType() == FileType.IMAGINARY);
+    }
+
+    /**
+     * Tests root of file system exists.
+     */
+    public void testRoot() throws FileSystemException
+    {
+        FileSystem fs = getReadFolder().getFileSystem();
+        String uri = fs.getRootURI();
+        final FileObject file = getManager().resolveFile(uri);
+        //final FileObject file = getReadFolder().getFileSystem().getRoot();
+        assertTrue(file.exists());
+        assertTrue(file.getType() != FileType.IMAGINARY);
+    }
+
+    /**
+     * Tests parent identity
+     */
+    public void testParent() throws FileSystemException
+    {
+        // Test when both exist
+        FileObject folder = getReadFolder().resolveFile("dir1");
+        FileObject child = folder.resolveFile("file3.txt");
+        assertTrue("folder exists", folder.exists());
+        assertTrue("child exists", child.exists());
+        assertSame(folder, child.getParent());
+
+        // Test when file does not exist
+        child = folder.resolveFile("unknown-file");
+        assertTrue("folder exists", folder.exists());
+        assertTrue("child does not exist", !child.exists());
+        assertSame(folder, child.getParent());
+
+        // Test when neither exists
+        folder = getReadFolder().resolveFile("unknown-folder");
+        child = folder.resolveFile("unknown-file");
+        assertTrue("folder does not exist", !folder.exists());
+        assertTrue("child does not exist", !child.exists());
+        assertSame(folder, child.getParent());
+
+        // Test the parent of the root of the file system
+        // TODO - refactor out test cases for layered vs originating fs
+        final FileSystem fileSystem = getReadFolder().getFileSystem();
+        FileObject root = fileSystem.getRoot();
+        if (fileSystem.getParentLayer() == null)
+        {
+            // No parent layer, so parent should be null
+            assertNull("root has null parent", root.getParent());
+        }
+        else
+        {
+            // Parent should be parent of parent layer.
+            assertSame(fileSystem.getParentLayer().getParent(), root.getParent());
+        }
+    }
+
+    /**
+     * Tests that children cannot be listed for non-folders.
+     */
+    public void testChildren() throws FileSystemException
+    {
+        // Check for file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertSame(FileType.FILE, file.getType());
+        try
+        {
+            file.getChildren();
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+            assertSameMessage("vfs.provider/list-children-not-folder.error", file, e);
+        }
+
+        // Should be able to get child by name
+        file = file.resolveFile("some-child");
+        assertNotNull(file);
+
+        // Check for unknown file
+        file = getReadFolder().resolveFile("unknown-file");
+        assertTrue(!file.exists());
+        try
+        {
+            file.getChildren();
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            assertSameMessage("vfs.provider/list-children-not-folder.error", file, e);
+        }
+
+        // Should be able to get child by name
+        FileObject child = file.resolveFile("some-child");
+        assertNotNull(child);
+    }
+
+    /**
+     * Tests content.
+     */
+    public void testContent() throws Exception
+    {
+        // Test non-empty file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertSameContent(FILE1_CONTENT, file);
+
+        // Test empty file
+        file = getReadFolder().resolveFile("empty.txt");
+        assertSameContent("", file);
+    }
+
+    /**
+     * Tests that unknown files have no content.
+     */
+    public void testUnknownContent() throws Exception
+    {
+
+        // Try getting the content of an unknown file
+        FileObject unknownFile = getReadFolder().resolveFile("unknown-file");
+        FileContent content = unknownFile.getContent();
+        try
+        {
+            content.getInputStream();
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+            assertSameMessage("vfs.provider/read-not-file.error", unknownFile, e);
+        }
+        try
+        {
+            content.getSize();
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            assertSameMessage("vfs.provider/get-size-not-file.error", unknownFile, e);
+        }
+    }
+
+    /**
+     * Tests concurrent reads on a file.
+     */
+    public void testConcurrentRead() throws Exception
+    {
+        final FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertTrue(file.exists());
+
+        // Start reading from the file
+        final InputStream instr = file.getContent().getInputStream();
+        try
+        {
+            // Start reading again
+            file.getContent().getInputStream().close();
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+
+    /**
+     * Tests concurrent reads on different files works.
+     */
+    public void testConcurrentReadFiles() throws Exception
+    {
+        final FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertTrue(file.exists());
+        final FileObject emptyFile = getReadFolder().resolveFile("empty.txt");
+        assertTrue(emptyFile.exists());
+
+        // Start reading from the file
+        final InputStream instr = file.getContent().getInputStream();
+        try
+        {
+            // Try to read from other file
+            assertSameContent("", emptyFile);
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+
+    /**
+     * Tests that content and file objects are usable after being closed.
+     */
+    public void testReuse() throws Exception
+    {
+        // Get the test file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertEquals(FileType.FILE, file.getType());
+
+        // Get the file content
+        assertSameContent(FILE1_CONTENT, file);
+
+        // Read the content again
+        assertSameContent(FILE1_CONTENT, file);
+
+        // Close the content + file
+        file.getContent().close();
+        file.close();
+
+        // Read the content again
+        assertSameContent(FILE1_CONTENT, file);
+    }
+
+    /**
+     * Tests that input streams are cleaned up on file close.
+     */
+    public void testInstrCleanup() throws Exception
+    {
+        // Get the test file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertEquals(FileType.FILE, file.getType());
+
+        // Open some input streams
+        final InputStream instr1 = file.getContent().getInputStream();
+        assertTrue(instr1.read() == FILE1_CONTENT.charAt(0));
+        final InputStream instr2 = file.getContent().getInputStream();
+        assertTrue(instr2.read() == FILE1_CONTENT.charAt(0));
+
+        // Close the file
+        file.close();
+
+        // Check
+        assertTrue(instr1.read() == -1);
+        assertTrue(instr2.read() == -1);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileInfo.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileInfo.java
new file mode 100644
index 0000000..623e8a4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileInfo.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.FileType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Info about a file.
+ */
+class FileInfo
+{
+    String baseName;
+    FileType type;
+    String content;
+    Map children = new HashMap();
+    FileInfo parent;
+
+    public FileInfo(final String name, final FileType type)
+    {
+        baseName = name;
+        this.type = type;
+        this.content = null;
+    }
+
+    public FileInfo(final String name, final FileType type, final String content)
+    {
+        baseName = name;
+        this.type = type;
+        this.content = content;
+    }
+
+    public FileInfo getParent()
+    {
+        return parent;
+    }
+
+    /**
+     * Adds a child.
+     */
+    public void addChild(final FileInfo child)
+    {
+        children.put(child.baseName, child);
+        child.parent = this;
+    }
+
+    /**
+     * Adds a child file.
+     */
+    public FileInfo addFile(final String baseName, final String content)
+    {
+        final FileInfo child = new FileInfo(baseName, FileType.FILE, content);
+        addChild(child);
+        return child;
+    }
+
+    /**
+     * Adds a child folder.
+     */
+    public FileInfo addFolder(final String baseName)
+    {
+        final FileInfo child = new FileInfo(baseName, FileType.FOLDER, null);
+        addChild(child);
+        return child;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileSystemManagerFactoryTestCase.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileSystemManagerFactoryTestCase.java
new file mode 100644
index 0000000..20da067
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/FileSystemManagerFactoryTestCase.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.VFS;
+
+import java.io.File;
+
+/**
+ * Test cases for the VFS factory.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileSystemManagerFactoryTestCase
+    extends AbstractVfsTestCase
+{
+    /**
+     * Sanity test.
+     */
+    public void testDefaultInstance() throws Exception
+    {
+        // Locate the default manager
+        final FileSystemManager manager = VFS.getManager();
+
+        // Lookup a test jar file
+        final File jarFile = getTestResource("test.jar");
+        FileObject file = manager.toFileObject(jarFile);
+        assertNotNull(file);
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+
+        // Expand it
+        file = manager.createFileSystem(file);
+        assertNotNull(file);
+        assertTrue(file.exists());
+        assertSame(FileType.FOLDER, file.getType());
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/LastModifiedTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/LastModifiedTests.java
new file mode 100644
index 0000000..f137fd6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/LastModifiedTests.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import junit.framework.AssertionFailedError;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * Test cases for getting and setting file last modified time.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class LastModifiedTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]{
+            Capability.GET_LAST_MODIFIED
+        };
+    }
+
+    /**
+     * Tests getting the last modified time of a file.
+     */
+    public void testGetLastModified() throws Exception
+    {
+        // Try a file.
+        final FileObject file = getReadFolder().resolveFile("file1.txt");
+        file.getContent().getLastModifiedTime();
+
+        // TODO - switch this on
+        // Try a folder
+        //final FileObject folder = getReadFolder().resolveFile( "dir1" );
+        //folder.getContent().getLastModifiedTime();
+    }
+
+    /**
+     * Tests setting the last modified time of file.
+     */
+    public void testSetLastModified() throws Exception
+    {
+        final long now = System.currentTimeMillis();
+
+        if (getReadFolder().getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE))
+        {
+            // Try a file
+            final FileObject file = getReadFolder().resolveFile("file1.txt");
+            file.getContent().setLastModifiedTime(now);
+            try
+            {
+                assertEquals(now, file.getContent().getLastModifiedTime(), file.getFileSystem().getLastModTimeAccuracy());
+            }
+            catch (AssertionFailedError e)
+            {
+                // on linux ext3 the above check is not necessarily true
+                if (file.getFileSystem().getLastModTimeAccuracy() < 1000L)
+                {
+                    assertEquals(now, file.getContent().getLastModifiedTime(), 1000L);
+                }
+                else
+                {
+                    throw e;
+                }
+            }
+        }
+
+        if (getReadFolder().getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FOLDER))
+        {
+            // Try a folder
+            final FileObject folder = getReadFolder().resolveFile("dir1");
+            folder.getContent().setLastModifiedTime(now);
+            try
+            {
+                assertEquals(now, folder.getContent().getLastModifiedTime(), folder.getFileSystem().getLastModTimeAccuracy());
+            }
+            catch (AssertionFailedError e)
+            {
+                // on linux ext3 the above check is not necessarily true
+                if (folder.getFileSystem().getLastModTimeAccuracy() < 1000L)
+                {
+                    assertEquals(now, folder.getContent().getLastModifiedTime(), 1000L);
+                }
+                else
+                {
+                    throw e;
+                }
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/NamingTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/NamingTests.java
new file mode 100644
index 0000000..2347a9d
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/NamingTests.java
@@ -0,0 +1,461 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.NameScope;
+
+/**
+ * Test cases for file naming.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Add tests for all FileName methods
+ */
+public class NamingTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Tests resolution of relative file names via the FS manager
+     */
+    public void testRelativeURI() throws Exception
+    {
+        // Build base dir
+        getManager().setBaseFile(getReadFolder());
+
+        // Locate the base dir
+        FileObject file = getManager().resolveFile(".");
+        assertSame("file object", getReadFolder(), file);
+
+        // Locate a child
+        file = getManager().resolveFile("some-child");
+        assertSame("file object", getReadFolder(), file.getParent());
+
+        // Locate a descendent
+        file = getManager().resolveFile("some-folder/some-file");
+        assertSame("file object", getReadFolder(), file.getParent().getParent());
+
+        // Locate parent
+        file = getManager().resolveFile("..");
+        assertSame("file object", getReadFolder().getParent(), file);
+
+        // free basefile
+        getManager().setBaseFile((FileObject) null);
+    }
+
+    /**
+     * Tests encoding of relative URI.
+     */
+    public void testRelativeUriEncoding() throws Exception
+    {
+        // Build base dir
+        getManager().setBaseFile(getReadFolder());
+        final String path = getReadFolder().getName().getPath();
+
+        // §1 Encode "some file"
+        FileObject file = getManager().resolveFile("%73%6f%6d%65%20%66%69%6c%65");
+        assertEquals(path + "/some file", file.getName().getPathDecoded());
+
+        // §2 Encode "."
+        file = getManager().resolveFile("%2e");
+        // 18-6-2005 imario@apache.org: no need to keep the "current directory"
+        // assertEquals(path + "/.", file.getName().getPathDecoded());
+        assertEquals(path, file.getName().getPathDecoded());
+
+        // §3 Encode '%'
+        file = getManager().resolveFile("a%25");
+        assertEquals(path + "/a%", file.getName().getPathDecoded());
+
+        // §4 Encode /
+        file = getManager().resolveFile("dir%2fchild");
+        assertEquals(path + "/dir/child", file.getName().getPathDecoded());
+
+        // §5 Encode \
+        file = getManager().resolveFile("dir%5cchild");
+        // 18-6-2005 imario@apache.org: all file separators normalized to "/"
+        // decided to do this to get the same behaviour as in §4 on windows
+        // platforms
+        // assertEquals(path + "/dir\\child", file.getName().getPathDecoded());
+        assertEquals(path + "/dir/child", file.getName().getPathDecoded());
+
+        // §6 Use "%" literal
+        try
+        {
+            getManager().resolveFile("%");
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+        }
+
+        // §7 Not enough digits in encoded char
+        try
+        {
+            getManager().resolveFile("%5");
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+        }
+
+        // §8 Invalid digit in encoded char
+        try
+        {
+            getManager().resolveFile("%q");
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+        }
+
+        // free basefile
+        getManager().setBaseFile((FileObject) null);
+    }
+
+    /**
+     * Tests the root file name.
+     */
+    public void testRootFileName() throws Exception
+    {
+        // Locate the root file
+        final FileName rootName = getReadFolder().getFileSystem().getRoot().getName();
+
+        // Test that the root path is "/"
+        assertEquals("root path", "/", rootName.getPath());
+
+        // Test that the root basname is ""
+        assertEquals("root base name", "", rootName.getBaseName());
+
+        // Test that the root name has no parent
+        assertNull("root parent", rootName.getParent());
+    }
+
+    /**
+     * Tests child file names.
+     */
+    public void testChildName() throws Exception
+    {
+        final FileName baseName = getReadFolder().getName();
+        final String basePath = baseName.getPath();
+        final FileName name = getManager().resolveName(baseName, "some-child", NameScope.CHILD);
+
+        // Test path is absolute
+        assertTrue("is absolute", basePath.startsWith("/"));
+
+        // Test base name
+        assertEquals("base name", "some-child", name.getBaseName());
+
+        // Test absolute path
+        assertEquals("absolute path", basePath + "/some-child", name.getPath());
+
+        // Test parent path
+        assertEquals("parent absolute path", basePath, name.getParent().getPath());
+
+        // Try using a compound name to find a child
+        assertBadName(name, "a/b", NameScope.CHILD);
+
+        // Check other invalid names
+        checkDescendentNames(name, NameScope.CHILD);
+    }
+
+    /**
+     * Name resolution tests that are common for CHILD or DESCENDENT scope.
+     */
+    private void checkDescendentNames(final FileName name,
+                                      final NameScope scope)
+        throws Exception
+    {
+        // Make some assumptions about the name
+        assertTrue(!name.getPath().equals("/"));
+        assertTrue(!name.getPath().endsWith("/a"));
+        assertTrue(!name.getPath().endsWith("/a/b"));
+
+        // Test names with the same prefix
+        String path = name.getPath() + "/a";
+        assertSameName(path, name, path, scope);
+        assertSameName(path, name, "../" + name.getBaseName() + "/a", scope);
+
+        // Test an empty name
+        assertBadName(name, "", scope);
+
+        // Test . name
+        assertBadName(name, ".", scope);
+        assertBadName(name, "./", scope);
+
+        // Test ancestor names
+        assertBadName(name, "..", scope);
+        assertBadName(name, "../a", scope);
+        assertBadName(name, "../" + name.getBaseName() + "a", scope);
+        assertBadName(name, "a/..", scope);
+
+        // Test absolute names
+        assertBadName(name, "/", scope);
+        assertBadName(name, "/a", scope);
+        assertBadName(name, "/a/b", scope);
+        assertBadName(name, name.getPath(), scope);
+        assertBadName(name, name.getPath() + "a", scope);
+    }
+
+    /**
+     * Checks that a relative name resolves to the expected absolute path.
+     * Tests both forward and back slashes.
+     */
+    private void assertSameName(final String expectedPath,
+                                final FileName baseName,
+                                final String relName,
+                                final NameScope scope)
+        throws Exception
+    {
+        // Try the supplied name
+        FileName name = getManager().resolveName(baseName, relName, scope);
+        assertEquals(expectedPath, name.getPath());
+
+        String temp;
+        
+        // Replace the separators
+        temp = relName.replace('\\', '/');
+        name = getManager().resolveName(baseName, temp, scope);
+        assertEquals(expectedPath, name.getPath());
+
+        // And again
+        temp = relName.replace('/', '\\');
+        name = getManager().resolveName(baseName, temp, scope);
+        assertEquals(expectedPath, name.getPath());
+    }
+
+    /**
+     * Checks that a relative name resolves to the expected absolute path.
+     * Tests both forward and back slashes.
+     */
+    private void assertSameName(String expectedPath,
+                                FileName baseName,
+                                String relName) throws Exception
+    {
+        assertSameName(expectedPath, baseName, relName, NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Tests relative name resolution, relative to the base folder.
+     */
+    public void testNameResolution() throws Exception
+    {
+        final FileName baseName = getReadFolder().getName();
+        final String parentPath = baseName.getParent().getPath();
+        final String path = baseName.getPath();
+        final String childPath = path + "/some-child";
+
+        // Test empty relative path
+        assertSameName(path, baseName, "");
+
+        // Test . relative path
+        assertSameName(path, baseName, ".");
+
+        // Test ./ relative path
+        assertSameName(path, baseName, "./");
+
+        // Test .// relative path
+        assertSameName(path, baseName, ".//");
+
+        // Test .///.///. relative path
+        assertSameName(path, baseName, ".///.///.");
+        assertSameName(path, baseName, "./\\/.\\//.");
+
+        // Test <elem>/.. relative path
+        assertSameName(path, baseName, "a/..");
+
+        // Test .. relative path
+        assertSameName(parentPath, baseName, "..");
+
+        // Test ../ relative path
+        assertSameName(parentPath, baseName, "../");
+
+        // Test ..//./ relative path
+        assertSameName(parentPath, baseName, "..//./");
+        assertSameName(parentPath, baseName, "..//.\\");
+
+        // Test <elem>/../.. relative path
+        assertSameName(parentPath, baseName, "a/../..");
+
+        // Test <elem> relative path
+        assertSameName(childPath, baseName, "some-child");
+
+        // Test ./<elem> relative path
+        assertSameName(childPath, baseName, "./some-child");
+
+        // Test ./<elem>/ relative path
+        assertSameName(childPath, baseName, "./some-child/");
+
+        // Test <elem>/././././ relative path
+        assertSameName(childPath, baseName, "./some-child/././././");
+
+        // Test <elem>/../<elem> relative path
+        assertSameName(childPath, baseName, "a/../some-child");
+
+        // Test <elem>/<elem>/../../<elem> relative path
+        assertSameName(childPath, baseName, "a/b/../../some-child");
+    }
+
+    /**
+     * Tests descendent name resolution.
+     */
+    public void testDescendentName()
+        throws Exception
+    {
+        final FileName baseName = getReadFolder().getName();
+
+        // Test direct child
+        String path = baseName.getPath() + "/some-child";
+        assertSameName(path, baseName, "some-child", NameScope.DESCENDENT);
+
+        // Test compound name
+        path = path + "/grand-child";
+        assertSameName(path, baseName, "some-child/grand-child", NameScope.DESCENDENT);
+
+        // Test relative names
+        assertSameName(path, baseName, "./some-child/grand-child", NameScope.DESCENDENT);
+        assertSameName(path, baseName, "./nada/../some-child/grand-child", NameScope.DESCENDENT);
+        assertSameName(path, baseName, "some-child/./grand-child", NameScope.DESCENDENT);
+
+        // Test badly formed descendent names
+        checkDescendentNames(baseName, NameScope.DESCENDENT);
+    }
+
+    /**
+     * Tests resolution of absolute names.
+     */
+    public void testAbsoluteNames() throws Exception
+    {
+        // Test against the base folder
+        FileName name = getReadFolder().getName();
+        checkAbsoluteNames(name);
+
+        // Test against the root
+        name = getReadFolder().getFileSystem().getRoot().getName();
+        checkAbsoluteNames(name);
+
+        // Test against some unknown file
+        name = getManager().resolveName(name, "a/b/unknown");
+        checkAbsoluteNames(name);
+    }
+
+    /**
+     * Tests resolution of absolute names.
+     */
+    private void checkAbsoluteNames(final FileName name) throws Exception
+    {
+        // Root
+        assertSameName("/", name, "/");
+        assertSameName("/", name, "//");
+        assertSameName("/", name, "/.");
+        assertSameName("/", name, "/some file/..");
+
+        // Some absolute names
+        assertSameName("/a", name, "/a");
+        assertSameName("/a", name, "/./a");
+        assertSameName("/a", name, "/a/.");
+        assertSameName("/a/b", name, "/a/b");
+
+        // Some bad names
+        assertBadName(name, "/..", NameScope.FILE_SYSTEM);
+        assertBadName(name, "/a/../..", NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Asserts that a particular relative name is invalid for a particular
+     * scope.
+     */
+    private void assertBadName(final FileName name,
+                               final String relName,
+                               final NameScope scope)
+    {
+        try
+        {
+            getManager().resolveName(name, relName, scope);
+            fail("expected failure");
+        }
+        catch (FileSystemException e)
+        {
+            // TODO - should check error message
+        }
+    }
+
+    /**
+     * Tests conversion from absolute to relative names.
+     */
+    public void testAbsoluteNameConvert() throws Exception
+    {
+        final FileName baseName = getReadFolder().getName();
+
+        String path = "/test1/test2";
+        FileName name = getManager().resolveName(baseName, path);
+        assertEquals(path, name.getPath());
+
+        // Try child and descendent names
+        testRelName(name, "child");
+        testRelName(name, "child1/child2");
+
+        // Try own name
+        testRelName(name, ".");
+
+        // Try parent, and root
+        testRelName(name, "..");
+        testRelName(name, "../..");
+
+        // Try sibling and descendent of sibling
+        testRelName(name, "../sibling");
+        testRelName(name, "../sibling/child");
+
+        // Try siblings with similar names
+        testRelName(name, "../test2_not");
+        testRelName(name, "../test2_not/child");
+        testRelName(name, "../test");
+        testRelName(name, "../test/child");
+
+        // Try unrelated
+        testRelName(name, "../../unrelated");
+        testRelName(name, "../../test");
+        testRelName(name, "../../test/child");
+
+        // Test against root
+        path = "/";
+        name = getManager().resolveName(baseName, path);
+        assertEquals(path, name.getPath());
+
+        // Try child and descendent names (against root)
+        testRelName(name, "child");
+        testRelName(name, "child1/child2");
+
+        // Try own name (against root)
+        testRelName(name, ".");
+    }
+
+    /**
+     * Checks that a file name converts to an expected relative path
+     */
+    private void testRelName(final FileName baseName,
+                             final String relPath)
+        throws Exception
+    {
+        final FileName expectedName = getManager().resolveName(baseName, relPath);
+
+        // Convert to relative path, and check
+        final String actualRelPath = baseName.getRelativeName(expectedName);
+        assertEquals(relPath, actualRelPath);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderCacheStrategyTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderCacheStrategyTests.java
new file mode 100644
index 0000000..c694e15
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderCacheStrategyTests.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.CacheStrategy;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.provider.ram.RamFileObject;
+import org.apache.commons.vfs.util.FileObjectUtils;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.impl.VirtualFileSystem;
+
+/**
+ * Test the cache stragey
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public class ProviderCacheStrategyTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.CREATE,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+        };
+    }
+
+    /**
+     * Test the manual cache strategy
+     */
+    public void testManualCache() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+        if (FileObjectUtils.isInstanceOf(getBaseFolder(), RamFileObject.class) ||
+            scratchFolder.getFileSystem() instanceof VirtualFileSystem)
+        {
+            // cant check ram filesystem as every manager holds its own ram filesystem data
+            return;
+        }
+
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        
+        DefaultFileSystemManager fs = createManager();
+        fs.setCacheStrategy(CacheStrategy.MANUAL);
+        fs.init();
+        FileObject foBase2 = getBaseTestFolder(fs);
+
+        FileObject cachedFolder = foBase2.resolveFile(scratchFolder.getName().getPath());
+        
+        FileObject[] fos = cachedFolder.getChildren();
+        assertContainsNot(fos, "file1.txt");
+        
+        scratchFolder.resolveFile("file1.txt").createFile();
+        
+        fos = cachedFolder.getChildren();
+        assertContainsNot(fos, "file1.txt");
+        
+        cachedFolder.refresh();
+        fos = cachedFolder.getChildren();
+        assertContains(fos, "file1.txt");
+    }
+
+    /**
+     * Test the on_resolve strategy
+     */
+    public void testOnResolveCache() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+        if (FileObjectUtils.isInstanceOf(getBaseFolder(), RamFileObject.class) ||
+            scratchFolder.getFileSystem() instanceof VirtualFileSystem)
+        {
+            // cant check ram filesystem as every manager holds its own ram filesystem data
+            return;
+        }
+
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        
+        DefaultFileSystemManager fs = createManager();
+        fs.setCacheStrategy(CacheStrategy.ON_RESOLVE);
+        fs.init();
+        FileObject foBase2 = getBaseTestFolder(fs);
+
+        FileObject cachedFolder = foBase2.resolveFile(scratchFolder.getName().getPath());
+        
+        FileObject[] fos = cachedFolder.getChildren();
+        assertContainsNot(fos, "file1.txt");
+        
+        scratchFolder.resolveFile("file1.txt").createFile();
+        
+        fos = cachedFolder.getChildren();
+        assertContainsNot(fos, "file1.txt");
+        
+        cachedFolder = foBase2.resolveFile(scratchFolder.getName().getPath());
+        fos = cachedFolder.getChildren();
+        assertContains(fos, "file1.txt");
+    }
+    
+    /**
+     * Test the on_call strategy
+     */
+    public void testOnCallCache() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+        if (FileObjectUtils.isInstanceOf(getBaseFolder(), RamFileObject.class) ||
+            scratchFolder.getFileSystem() instanceof VirtualFileSystem)
+        {
+            // cant check ram filesystem as every manager holds its own ram filesystem data
+            return;
+        }
+
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        
+        DefaultFileSystemManager fs = createManager();
+        fs.setCacheStrategy(CacheStrategy.ON_CALL);
+        fs.init();
+        FileObject foBase2 = getBaseTestFolder(fs);
+
+        FileObject cachedFolder = foBase2.resolveFile(scratchFolder.getName().getPath());
+        
+        FileObject[] fos = cachedFolder.getChildren();
+        assertContainsNot(fos, "file1.txt");
+        
+        scratchFolder.resolveFile("file1.txt").createFile();
+        
+        fos = cachedFolder.getChildren();
+        assertContains(fos, "file1.txt");
+    }
+    
+    public void assertContainsNot(FileObject[] fos, String string)
+    {
+        for (int i = 0; i<fos.length; i++)
+        {
+            if (string.equals(fos[i].getName().getBaseName()))
+            {
+                fail(string + " should not be seen");
+            }
+        }
+    }
+    
+    public void assertContains(FileObject[] fos, String string)
+    {
+        for (int i = 0; i<fos.length; i++)
+        {
+            if (string.equals(fos[i].getName().getBaseName()))
+            {
+                return;
+            }
+        }
+        
+        fail(string + " should be seen");
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderDeleteTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderDeleteTests.java
new file mode 100644
index 0000000..e63747e
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderDeleteTests.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelectInfo;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileTypeSelector;
+import org.apache.commons.vfs.Selectors;
+
+/**
+ * File system test that do some delete operations.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public class ProviderDeleteTests
+    extends AbstractProviderTestCase
+{
+    private class FileNameSelector implements FileSelector
+    {
+        final String basename;
+
+        private FileNameSelector(String basename)
+        {
+            this.basename = basename;
+        }
+
+        public boolean includeFile(FileSelectInfo fileInfo) throws Exception
+        {
+            return this.basename.equals(fileInfo.getFile().getName().getBaseName());
+        }
+
+        public boolean traverseDescendents(FileSelectInfo fileInfo) throws Exception
+        {
+            return true;
+        }
+    }
+
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.CREATE,
+            Capability.DELETE,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+        };
+    }
+
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        final FileObject dir1 = scratchFolder.resolveFile("dir1");
+        dir1.createFolder();
+        final FileObject dir1file1 = dir1.resolveFile("a.txt");
+        dir1file1.createFile();
+        final FileObject dir2 = scratchFolder.resolveFile("dir2");
+        dir2.createFolder();
+        final FileObject dir2file1 = dir2.resolveFile("b.txt");
+        dir2file1.createFile();
+
+        return scratchFolder;
+    }
+
+    /**
+     * deletes the complete structure
+     */
+    public void testDeleteFiles() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        assertEquals(scratchFolder.delete(Selectors.EXCLUDE_SELF), 4);
+    }
+
+    /**
+     * deletes a single file
+     */
+    public void testDeleteFile() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        final FileObject file = scratchFolder.resolveFile("dir1/a.txt");
+
+        assertTrue(file.delete());
+    }
+
+    /**
+     * Deletes a non existent file
+     */
+    public void testDeleteNonExistantFile() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        final FileObject file = scratchFolder.resolveFile("dir1/aa.txt");
+
+        assertFalse(file.delete());
+    }
+
+    /**
+     * deletes files
+     */
+    public void testDeleteAllFiles() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        assertEquals(scratchFolder.delete(new FileTypeSelector(FileType.FILE)), 2);
+    }
+
+    /**
+     * deletes a.txt
+     */
+    public void testDeleteOneFiles() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        assertEquals(scratchFolder.delete(new FileNameSelector("a.txt")), 1);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadTests.java
new file mode 100644
index 0000000..140e298
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadTests.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * RanomdRead-only test cases for file providers.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class ProviderRandomReadTests
+    extends AbstractProviderTestCase
+{
+    private final String TEST_DATA = "This is a test file.";
+
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.GET_TYPE,
+            Capability.RANDOM_ACCESS_READ
+        };
+    }
+
+    /**
+     * Read a file
+     */
+    public void testRandomRead() throws Exception
+    {
+        FileObject file = null;
+        try
+        {
+            file = getReadFolder().resolveFile("file1.txt");
+            RandomAccessContent ra = file.getContent().getRandomAccessContent(RandomAccessMode.READ);
+
+            // read first byte
+            byte c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(0));
+            assertEquals("fp", ra.getFilePointer(), 1);
+
+            // start at pos 4
+            ra.seek(3);
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(3));
+            assertEquals("fp", ra.getFilePointer(), 4);
+
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(4));
+            assertEquals("fp", ra.getFilePointer(), 5);
+
+            // restart at pos 4
+            ra.seek(3);
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(3));
+            assertEquals("fp", ra.getFilePointer(), 4);
+
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(4));
+            assertEquals("fp", ra.getFilePointer(), 5);
+
+            // advance to pos 11
+            ra.seek(10);
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(10));
+            assertEquals("fp", ra.getFilePointer(), 11);
+
+            c = ra.readByte();
+            assertEquals(c, TEST_DATA.charAt(11));
+            assertEquals("fp", ra.getFilePointer(), 12);
+        }
+        finally
+        {
+            if (file != null)
+            {
+                file.close();
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadWriteTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadWriteTests.java
new file mode 100644
index 0000000..21bc18a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRandomReadWriteTests.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.RandomAccessContent;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+/**
+ * RanomdRead/Write test cases for file providers.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class ProviderRandomReadWriteTests
+    extends AbstractProviderTestCase
+{
+    private final String TEST_DATA = "This is a test file.";
+
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.GET_TYPE,
+            Capability.CREATE,
+            Capability.RANDOM_ACCESS_READ,
+            Capability.RANDOM_ACCESS_WRITE
+        };
+    }
+
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
+    /**
+     * Read a file
+     */
+    public void testRandomWrite() throws Exception
+    {
+        FileObject file = null;
+        try
+        {
+            file = createScratchFolder().resolveFile("random_write.txt");
+            file.createFile();
+            RandomAccessContent ra = file.getContent().getRandomAccessContent(RandomAccessMode.READWRITE);
+
+            // write first byte
+            ra.writeByte(TEST_DATA.charAt(0));
+
+            // start at pos 4
+            ra.seek(3);
+            ra.writeByte(TEST_DATA.charAt(3));
+            ra.writeByte(TEST_DATA.charAt(4));
+
+            // restart at pos 4 (but overwrite with different content)
+            ra.seek(3);
+            ra.writeByte(TEST_DATA.charAt(7));
+            ra.writeByte(TEST_DATA.charAt(8));
+
+            // advance to pos 11
+            ra.seek(10);
+            ra.writeByte(TEST_DATA.charAt(10));
+            ra.writeByte(TEST_DATA.charAt(11));
+
+            // now read
+            ra.seek(0);
+            assertEquals(ra.readByte(), TEST_DATA.charAt(0));
+
+            ra.seek(3);
+            assertEquals(ra.readByte(), TEST_DATA.charAt(7));
+            assertEquals(ra.readByte(), TEST_DATA.charAt(8));
+
+            ra.seek(10);
+            assertEquals(ra.readByte(), TEST_DATA.charAt(10));
+            assertEquals(ra.readByte(), TEST_DATA.charAt(11));
+        }
+        finally
+        {
+            if (file != null)
+            {
+                file.close();
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderReadTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderReadTests.java
new file mode 100644
index 0000000..d8ed6e6
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderReadTests.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileSystem;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Read-only test cases for file providers.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ * @todo Test getLastModified(), getAttribute()
+ */
+public class ProviderReadTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT
+        };
+    }
+
+    /**
+     * Walks the base folder structure, asserting it contains exactly the
+     * expected files and folders.
+     */
+    public void testStructure() throws Exception
+    {
+        final FileInfo baseInfo = buildExpectedStructure();
+        assertSameStructure(getReadFolder(), baseInfo);
+    }
+
+    /**
+     * Walks a folder structure, asserting it contains exactly the
+     * expected files and folders.
+     */
+    protected void assertSameStructure(final FileObject folder,
+                                       final FileInfo expected)
+        throws Exception
+    {
+        // Setup the structure
+        final List queueExpected = new ArrayList();
+        queueExpected.add(expected);
+
+        final List queueActual = new ArrayList();
+        queueActual.add(folder);
+
+        while (queueActual.size() > 0)
+        {
+            final FileObject file = (FileObject) queueActual.remove(0);
+            final FileInfo info = (FileInfo) queueExpected.remove(0);
+
+            // Check the type is correct
+            assertSame(info.type, file.getType());
+
+            if (info.type == FileType.FILE)
+            {
+                continue;
+            }
+
+            // Check children
+            final FileObject[] children = file.getChildren();
+
+            // Make sure all children were found
+            assertNotNull(children);
+            int length = children.length;
+            if (info.children.size() != children.length)
+            {
+                for (int i=0; i < children.length; ++i)
+                {
+                    if (children[i].getName().getBaseName().startsWith("."))
+                    {
+                        --length;
+                        continue;
+                    }
+                    System.out.println(children[i].getName());
+                }
+            }
+
+            assertEquals("count children of \"" + file.getName() + "\"", info.children.size(), length);
+
+            // Recursively check each child
+            for (int i = 0; i < children.length; i++)
+            {
+                final FileObject child = children[i];
+                String childName = child.getName().getBaseName();
+                if (childName.startsWith("."))
+                {
+                    continue;
+                }
+                final FileInfo childInfo = (FileInfo) info.children.get(childName);
+
+                // Make sure the child is expected
+                assertNotNull(childInfo);
+
+                // Add to the queue of files to check
+                queueExpected.add(childInfo);
+                queueActual.add(child);
+            }
+        }
+    }
+
+    /**
+     * Tests type determination.
+     */
+    public void testType() throws Exception
+    {
+        // Test a file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertSame(FileType.FILE, file.getType());
+
+        // Test a folder
+        file = getReadFolder().resolveFile("dir1");
+        assertSame(FileType.FOLDER, file.getType());
+
+        // Test an unknown file
+        file = getReadFolder().resolveFile("unknown-child");
+        assertSame(FileType.IMAGINARY, file.getType());
+    }
+
+    /**
+     * Tests the contents of root of file system can be listed.
+     */
+    public void testRoot() throws FileSystemException
+    {
+        FileSystem fs = getReadFolder().getFileSystem();
+        String uri = fs.getRootURI();
+        final FileObject file = getManager().resolveFile(uri);
+        file.getChildren();
+    }
+
+    /**
+     * Tests that folders have no content.
+     */
+    public void testFolderContent() throws Exception
+    {
+        if (getReadFolder().getFileSystem().hasCapability(Capability.DIRECTORY_READ_CONTENT))
+        {
+            // test wont fail
+            return;
+        }
+
+        // Try getting the content of a folder
+        FileObject folder = getReadFolder().resolveFile("dir1");
+        try
+        {
+            folder.getContent().getInputStream();
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+            assertSameMessage("vfs.provider/read-not-file.error", folder, e);
+        }
+    }
+
+    /**
+     * Tests can perform operations on a folder while reading from a different files.
+     */
+    public void testConcurrentReadFolder() throws Exception
+    {
+        final FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertTrue(file.exists());
+        final FileObject folder = getReadFolder().resolveFile("dir1");
+        assertTrue(folder.exists());
+
+        // Start reading from the file
+        final InputStream instr = file.getContent().getInputStream();
+        try
+        {
+            // Do some operations
+            folder.exists();
+            folder.getType();
+            folder.getChildren();
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+
+    /**
+     * Tests that findFiles() works.
+     */
+    public void testFindFiles() throws Exception
+    {
+        final FileInfo fileInfo = buildExpectedStructure();
+        final VerifyingFileSelector selector = new VerifyingFileSelector(fileInfo);
+
+        // Find the files
+        final FileObject[] actualFiles = getReadFolder().findFiles(selector);
+
+        // Compare actual and expected list of files
+        final List expectedFiles = selector.finish();
+        assertEquals(expectedFiles.size(), actualFiles.length);
+        final int count = expectedFiles.size();
+        for (int i = 0; i < count; i++)
+        {
+            final FileObject expected = (FileObject) expectedFiles.get(i);
+            final FileObject actual = actualFiles[i];
+            assertEquals(expected, actual);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRenameTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRenameTests.java
new file mode 100644
index 0000000..a6ff48f
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderRenameTests.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.Selectors;
+
+import java.io.OutputStream;
+
+/**
+ * File system test that check that a file system can be renamed.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public class ProviderRenameTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.CREATE,
+            Capability.DELETE,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT,
+            Capability.WRITE_CONTENT,
+            Capability.RENAME
+        };
+    }
+
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
+    /**
+     * Tests create-delete-create-a-file sequence on the same file system.
+     */
+    public void testRenameFile() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+        assertSameContent(content, file);
+
+
+        // Make sure we can move the new file to another file on the same filesystem
+
+        FileObject fileMove = scratchFolder.resolveFile("file1move.txt");
+        assertTrue(!fileMove.exists());
+
+        file.moveTo(fileMove);
+
+        assertTrue(!file.exists());
+        assertTrue(fileMove.exists());
+
+        assertSameContent(content, fileMove);
+
+        // Delete the file.
+        assertTrue(fileMove.exists());
+        assertTrue(fileMove.delete());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestConfig.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestConfig.java
new file mode 100644
index 0000000..2ffb2a1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestConfig.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+
+/**
+ * Test configuration for a file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public interface ProviderTestConfig
+{
+    /**
+     * Returns a DefaultFileSystemManager instance (or subclass instance).
+     */
+    public DefaultFileSystemManager getDefaultFileSystemManager();
+
+    /**
+     * Prepares the file system manager.
+     */
+    void prepare(DefaultFileSystemManager manager) throws Exception;
+
+    /**
+     * Returns the base folder for tests.  This folder must exist, and contain
+     * the following structure:
+     * <ul>
+     * <li>/read-tests
+     * <li>/write-tests
+     * </ul>
+     */
+    FileObject getBaseTestFolder(FileSystemManager manager) throws Exception;
+
+    /**
+     * Returns the filesCache implementation used for tests.
+     */
+    FilesCache getFilesCache();
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestSuite.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestSuite.java
new file mode 100644
index 0000000..c07ffbe
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderTestSuite.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.impl.test.VfsClassLoaderTests;
+
+/**
+ * The suite of tests for a file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Id$
+ */
+public class ProviderTestSuite
+    extends AbstractTestSuite
+{
+    /**
+     * Adds the tests for a file system to this suite.
+     */
+    public ProviderTestSuite(final ProviderTestConfig providerConfig) throws Exception
+    {
+        this(providerConfig, "", false, false);
+    }
+
+    /**
+     * Adds the tests for a file system to this suite. Provider has an empty directory.
+     */
+    public ProviderTestSuite(final ProviderTestConfig providerConfig,
+                             final boolean addEmptyDir) throws Exception
+    {
+        this(providerConfig, "", false, addEmptyDir);
+    }
+
+
+
+    protected ProviderTestSuite(final ProviderTestConfig providerConfig,
+                                final String prefix,
+                                final boolean nested,
+                                final boolean addEmptyDir)
+        throws Exception
+    {
+        super(providerConfig, prefix, nested, addEmptyDir);
+    }
+
+    /**
+     * Adds base tests - excludes the nested test cases.
+     */
+    protected void addBaseTests() throws Exception
+    {
+        addTests(ProviderCacheStrategyTests.class);
+        addTests(UriTests.class);
+        addTests(NamingTests.class);
+        addTests(ContentTests.class);
+        addTests(ProviderReadTests.class);
+        addTests(ProviderRandomReadTests.class);
+        addTests(ProviderWriteTests.class);
+        addTests(ProviderWriteAppendTests.class);
+        addTests(ProviderRandomReadWriteTests.class);
+        addTests(ProviderRenameTests.class);
+        addTests(ProviderDeleteTests.class);
+        addTests(LastModifiedTests.class);
+        addTests(UrlTests.class);
+        addTests(UrlStructureTests.class);
+        addTests(VfsClassLoaderTests.class);
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteAppendTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteAppendTests.java
new file mode 100644
index 0000000..32ae5dd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteAppendTests.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.Selectors;
+
+import java.io.OutputStream;
+
+/**
+ * File system test that check that a file system can be modified.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ */
+public class ProviderWriteAppendTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.CREATE,
+            Capability.DELETE,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT,
+            Capability.WRITE_CONTENT,
+            Capability.APPEND_CONTENT
+        };
+    }
+
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
+    /**
+     * Tests create-delete-create-a-file sequence on the same file system.
+     */
+    public void testAppendContent() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final String contentAppend = content + content;
+
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+        assertSameContent(content, file);
+
+        // Append to the new file
+        final OutputStream os2 = file.getContent().getOutputStream(true);
+        try
+        {
+            os2.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os2.close();
+        }
+        assertSameContent(contentAppend, file);
+
+        // Make sure we can copy the new file to another file on the same filesystem
+        FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
+        assertTrue(!fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(contentAppend, fileCopy);
+
+        // Delete the file.
+        assertTrue(fileCopy.exists());
+        assertTrue(fileCopy.delete());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteTests.java
new file mode 100644
index 0000000..8212734
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/ProviderWriteTests.java
@@ -0,0 +1,641 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileChangeEvent;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.Selectors;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * File system test that check that a file system can be modified.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class ProviderWriteTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.CREATE,
+            Capability.DELETE,
+            Capability.GET_TYPE,
+            Capability.LIST_CHILDREN,
+            Capability.READ_CONTENT,
+            Capability.WRITE_CONTENT
+        };
+    }
+
+    /**
+     * Sets up a scratch folder for the test to use.
+     */
+    protected FileObject createScratchFolder() throws Exception
+    {
+        FileObject scratchFolder = getWriteFolder();
+
+        // Make sure the test folder is empty
+        scratchFolder.delete(Selectors.EXCLUDE_SELF);
+        scratchFolder.createFolder();
+
+        return scratchFolder;
+    }
+
+    /**
+     * Tests folder creation.
+     */
+    public void testFolderCreate() throws Exception
+    {
+        FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        FileObject folder = scratchFolder.resolveFile("dir1");
+        assertTrue(!folder.exists());
+        folder.createFolder();
+        assertTrue(folder.exists());
+        assertSame(FileType.FOLDER, folder.getType());
+        assertEquals(0, folder.getChildren().length);
+
+        // Create a descendant, where the intermediate folders don't exist
+        folder = scratchFolder.resolveFile("dir2/dir1/dir1");
+        assertTrue(!folder.exists());
+        assertTrue(!folder.getParent().exists());
+        assertTrue(!folder.getParent().getParent().exists());
+        folder.createFolder();
+        assertTrue(folder.exists());
+        assertSame(FileType.FOLDER, folder.getType());
+        assertEquals(0, folder.getChildren().length);
+        assertTrue(folder.getParent().exists());
+        assertTrue(folder.getParent().getParent().exists());
+
+        // Test creating a folder that already exists
+        assertTrue(folder.exists());
+        folder.createFolder();
+    }
+
+    /**
+     * Tests file creation
+     */
+    public void testFileCreate() throws Exception
+    {
+        FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+        assertEquals(0, file.getContent().getSize());
+        assertFalse(file.isHidden());
+        assertTrue(file.isReadable());
+        assertTrue(file.isWriteable());
+        
+        // Create direct child of the test folder - special name
+        file = scratchFolder.resolveFile("file1%25.txt");
+        assertTrue(!file.exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+        assertEquals(0, file.getContent().getSize());
+        assertFalse(file.isHidden());
+        assertTrue(file.isReadable());
+        assertTrue(file.isWriteable());
+
+        // Create a descendant, where the intermediate folders don't exist
+        file = scratchFolder.resolveFile("dir1/dir1/file1.txt");
+        assertTrue(!file.exists());
+        assertTrue(!file.getParent().exists());
+        assertTrue(!file.getParent().getParent().exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertSame(FileType.FILE, file.getType());
+        assertEquals(0, file.getContent().getSize());
+        assertTrue(file.getParent().exists());
+        assertTrue(file.getParent().getParent().exists());
+        assertFalse(file.getParent().isHidden());
+        assertFalse(file.getParent().getParent().isHidden());
+        
+        // Test creating a file that already exists
+        assertTrue(file.exists());
+        file.createFile();
+        assertTrue(file.exists());
+        assertTrue(file.isReadable());
+        assertTrue(file.isWriteable());
+    }
+
+    /**
+     * Tests file/folder creation with mismatched types.
+     */
+    public void testFileCreateMismatched() throws Exception
+    {
+        FileObject scratchFolder = createScratchFolder();
+
+        // Create a test file and folder
+        FileObject file = scratchFolder.resolveFile("dir1/file1.txt");
+        file.createFile();
+        assertEquals(FileType.FILE, file.getType());
+
+        FileObject folder = scratchFolder.resolveFile("dir1/dir2");
+        folder.createFolder();
+        assertEquals(FileType.FOLDER, folder.getType());
+
+        // Attempt to create a file that already exists as a folder
+        try
+        {
+            folder.createFile();
+            fail();
+        }
+        catch (FileSystemException exc)
+        {
+        }
+
+        // Attempt to create a folder that already exists as a file
+        try
+        {
+            file.createFolder();
+            fail();
+        }
+        catch (FileSystemException exc)
+        {
+        }
+
+        // Attempt to create a folder as a child of a file
+        FileObject folder2 = file.resolveFile("some-child");
+        try
+        {
+            folder2.createFolder();
+            fail();
+        }
+        catch (FileSystemException exc)
+        {
+        }
+    }
+
+    /**
+     * Tests deletion
+     */
+    public void testDelete() throws Exception
+    {
+        // Set-up the test structure
+        FileObject folder = createScratchFolder();
+        folder.resolveFile("file1.txt").createFile();
+        folder.resolveFile("file%25.txt").createFile();
+        folder.resolveFile("emptydir").createFolder();
+        folder.resolveFile("dir1/file1.txt").createFile();
+        folder.resolveFile("dir1/dir2/file2.txt").createFile();
+
+        // Delete a file
+        FileObject file = folder.resolveFile("file1.txt");
+        assertTrue(file.exists());
+        file.delete(Selectors.SELECT_ALL);
+        assertTrue(!file.exists());
+
+        // Delete a special name file
+        file = folder.resolveFile("file%25.txt");
+        assertTrue(file.exists());
+        file.delete(Selectors.SELECT_ALL);
+        assertTrue(!file.exists());
+
+        // Delete an empty folder
+        file = folder.resolveFile("emptydir");
+        assertTrue(file.exists());
+        file.delete(Selectors.SELECT_ALL);
+        assertTrue(!file.exists());
+
+        // Recursive delete
+        file = folder.resolveFile("dir1");
+        FileObject file2 = file.resolveFile("dir2/file2.txt");
+        assertTrue(file.exists());
+        assertTrue(file2.exists());
+        file.delete(Selectors.SELECT_ALL);
+        assertTrue(!file.exists());
+        assertTrue(!file2.exists());
+
+        // Delete a file that does not exist
+        file = folder.resolveFile("some-folder/some-file");
+        assertTrue(!file.exists());
+        file.delete(Selectors.SELECT_ALL);
+        assertTrue(!file.exists());
+    }
+
+    /**
+     * Tests concurrent read and write on the same file fails.
+     */
+    /* imario@apache.org leave this to some sort of LockManager
+    public void testConcurrentReadWrite() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        file.createFile();
+
+        // Start reading from the file
+        final InputStream instr = file.getContent().getInputStream();
+
+        try
+        {
+            // Try to write to the file
+            file.getContent().getOutputStream();
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            // Check error message
+            assertSameMessage("vfs.provider/write-in-use.error", file, e);
+        }
+        finally
+        {
+            instr.close();
+        }
+    }
+    */
+
+    /**
+     * Tests concurrent writes on the same file fails.
+     */
+    /* imario@apache.org leave this to some sort of LockManager
+    public void testConcurrentWrite() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        file.createFile();
+
+        // Start writing to the file
+        final OutputStream outstr = file.getContent().getOutputStream();
+        final String testContent = "some content";
+        try
+        {
+            // Write some content to the first stream
+            outstr.write(testContent.getBytes());
+
+            // Try to open another output stream
+            file.getContent().getOutputStream();
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            // Check error message
+            assertSameMessage("vfs.provider/write-in-use.error", file, e);
+        }
+        finally
+        {
+            outstr.close();
+        }
+
+        // Make sure that the content written to the first stream is actually applied
+        assertSameContent(testContent, file);
+    }
+    */
+
+    /**
+     * Tests file copy to and from the same filesystem type.  This was a problem
+     * w/ FTP.
+     */
+    public void testCopySameFileSystem() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+
+        assertSameContent(content, file);
+
+        // Make sure we can copy the new file to another file on the same filesystem
+        FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
+        assertTrue(!fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(content, fileCopy);
+    }
+
+    /**
+     * Tests overwriting a file on the same file system.
+     */
+    public void testOverwriteSameFileSystem() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+
+        assertSameContent(content, file);
+
+        // Make sure we can copy the new file to another file on the same filesystem
+        FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
+        assertTrue(!fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(content, fileCopy);
+        
+        // Make sure we can copy the same new file to the same target file on the same filesystem
+        assertTrue(fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(content, fileCopy);
+    }
+
+    /**
+     * Tests create-delete-create-a-file sequence on the same file system.
+     */
+    public void testCreateDeleteCreateSameFileSystem() throws Exception
+    {
+        final FileObject scratchFolder = createScratchFolder();
+
+        // Create direct child of the test folder
+        final FileObject file = scratchFolder.resolveFile("file1.txt");
+        assertTrue(!file.exists());
+
+        // Create the source file
+        final String content = "Here is some sample content for the file.  Blah Blah Blah.";
+        final OutputStream os = file.getContent().getOutputStream();
+        try
+        {
+            os.write(content.getBytes("utf-8"));
+        }
+        finally
+        {
+            os.close();
+        }
+
+        assertSameContent(content, file);
+
+        // Make sure we can copy the new file to another file on the same filesystem
+        FileObject fileCopy = scratchFolder.resolveFile("file1copy.txt");
+        assertTrue(!fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(content, fileCopy);
+
+        // Delete the file.
+        assertTrue(fileCopy.exists());
+        assertTrue(fileCopy.delete());
+        
+        // Make sure we can copy the same new file to the same target file on the same filesystem
+        assertTrue(!fileCopy.exists());
+        fileCopy.copyFrom(file, Selectors.SELECT_SELF);
+
+        assertSameContent(content, fileCopy);
+    }
+
+    /**
+     * Test that children are handled correctly by create and delete.
+     */
+    public void testListChildren() throws Exception
+    {
+        FileObject folder = createScratchFolder();
+        HashSet names = new HashSet();
+
+        // Make sure the folder is empty
+        assertEquals(0, folder.getChildren().length);
+
+        // Create a child folder
+        folder.resolveFile("dir1").createFolder();
+        names.add("dir1");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Create a child file
+        folder.resolveFile("file1.html").createFile();
+        names.add("file1.html");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Create a descendent
+        folder.resolveFile("dir2/file1.txt").createFile();
+        names.add("dir2");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Create a child file via an output stream
+        OutputStream outstr = folder.resolveFile("file2.txt").getContent().getOutputStream();
+        outstr.close();
+        names.add("file2.txt");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Delete a child folder
+        folder.resolveFile("dir1").delete(Selectors.SELECT_ALL);
+        names.remove("dir1");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Delete a child file
+        folder.resolveFile("file1.html").delete(Selectors.SELECT_ALL);
+        names.remove("file1.html");
+        assertSameFileSet(names, folder.getChildren());
+
+        // Recreate the folder
+        folder.delete(Selectors.SELECT_ALL);
+        folder.createFolder();
+        assertEquals(0, folder.getChildren().length);
+    }
+
+    /**
+     * Check listeners are notified of changes.
+     */
+    public void testListener() throws Exception
+    {
+        final FileObject baseFile = createScratchFolder();
+
+        FileObject child = baseFile.resolveFile("newfile.txt");
+        assertTrue(!child.exists());
+
+        FileSystem fs = baseFile.getFileSystem();
+        TestListener listener = new TestListener(child);
+        fs.addListener(child, listener);
+
+        // Create as a folder
+        listener.addCreateEvent();
+        child.createFolder();
+        listener.assertFinished();
+
+        // Create the folder again.  Should not get an event.
+        child.createFolder();
+
+        // Delete
+        listener.addDeleteEvent();
+        child.delete();
+        listener.assertFinished();
+
+        // Delete again.  Should not get an event
+        child.delete();
+
+        // Create as a file
+        listener.addCreateEvent();
+        child.createFile();
+        listener.assertFinished();
+
+        // Create the file again.  Should not get an event
+        child.createFile();
+
+        listener.addDeleteEvent();
+        child.delete();
+
+        // Create as a file, by writing to it.
+        listener.addCreateEvent();
+        child.getContent().getOutputStream().close();
+        listener.assertFinished();
+
+        // Recreate the file by writing to it
+        child.getContent().getOutputStream().close();
+
+        // Copy another file over the top
+        final FileObject otherChild = baseFile.resolveFile("folder1");
+        otherChild.createFolder();
+        listener.addDeleteEvent();
+        listener.addCreateEvent();
+        child.copyFrom(otherChild, Selectors.SELECT_SELF);
+        listener.assertFinished();
+
+        fs.removeListener(child, listener);
+    }
+
+    /**
+     * Ensures the names of a set of files match an expected set.
+     */
+    private void assertSameFileSet(Set names, FileObject[] files)
+    {
+        // Make sure the sets are the same length
+        assertEquals(names.size(), files.length);
+
+        // Check for unexpected names
+        for (int i = 0; i < files.length; i++)
+        {
+            FileObject file = files[i];
+            assertTrue(names.contains(file.getName().getBaseName()));
+        }
+    }
+
+    /**
+     * A test listener.
+     */
+    private static class TestListener implements FileListener
+    {
+        private final FileObject file;
+        private final ArrayList events = new ArrayList();
+        private static final Object CREATE = "create";
+        private static final Object DELETE = "delete";
+        private static final Object CHANGED = "changed";
+
+        public TestListener(final FileObject file)
+        {
+            this.file = file;
+        }
+
+        /**
+         * Called when a file is created.
+         */
+        public void fileCreated(final FileChangeEvent event)
+        {
+            assertTrue("Unexpected create event", events.size() > 0);
+            assertSame("Expecting a create event", CREATE, events.remove(0));
+            assertSame(file, event.getFile());
+            try
+            {
+                assertTrue(file.exists());
+            }
+            catch (FileSystemException e)
+            {
+                fail();
+            }
+        }
+
+        /**
+         * Called when a file is deleted.
+         */
+        public void fileDeleted(final FileChangeEvent event)
+        {
+            assertTrue("Unexpected delete event", events.size() > 0);
+            assertSame("Expecting a delete event", DELETE, events.remove(0));
+            assertSame(file, event.getFile());
+            try
+            {
+                assertTrue(!file.exists());
+            }
+            catch (FileSystemException e)
+            {
+                fail();
+            }
+        }
+
+        public void fileChanged(FileChangeEvent event) throws Exception
+        {
+            assertTrue("Unexpected changed event", events.size() > 0);
+            assertSame("Expecting a changed event", CHANGED, events.remove(0));
+            assertSame(file, event.getFile());
+            try
+            {
+                assertTrue(!file.exists());
+            }
+            catch (FileSystemException e)
+            {
+                fail();
+            }
+        }
+
+        public void addCreateEvent()
+        {
+            events.add(CREATE);
+        }
+
+        public void addDeleteEvent()
+        {
+            events.add(DELETE);
+        }
+
+        public void assertFinished()
+        {
+            assertEquals("Missing event", 0, events.size());
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UriTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UriTests.java
new file mode 100644
index 0000000..863f663
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UriTests.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * Absolute URI test cases.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UriTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]{Capability.URI};
+    }
+
+    /**
+     * Tests resolution of absolute URI.
+     */
+    public void testAbsoluteURI() throws Exception
+    {
+        final FileObject readFolder = getReadFolder();
+
+        // Try fetching base folder again by its URI
+        final String uri = readFolder.getName().getURI();
+        FileObject file = getManager().resolveFile(uri, readFolder.getFileSystem().getFileSystemOptions());
+        assertSame("file object", readFolder, file);
+
+        // Try fetching the filesystem root by its URI
+        final String rootUri = readFolder.getName().getRootURI();
+        file = getManager().resolveFile(rootUri, readFolder.getFileSystem().getFileSystemOptions());
+        assertSame(readFolder.getFileSystem().getRoot(), file);
+        assertEquals(rootUri, file.getName().getRootURI());
+        assertEquals(rootUri, file.getName().getURI());
+        assertEquals(FileName.ROOT_PATH, file.getName().getPath());
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlStructureTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlStructureTests.java
new file mode 100644
index 0000000..11e4611
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlStructureTests.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import java.io.IOException;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+
+/**
+ * URL Test cases for providers that supply structural info.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlStructureTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]
+        {
+            Capability.GET_TYPE,
+            Capability.URI
+        };
+    }
+
+    /**
+     * Tests that folders have no content.
+     */
+    public void testFolderURL() throws Exception
+    {
+        final FileObject folder = getReadFolder().resolveFile("dir1");
+        if (folder.getFileSystem().hasCapability(Capability.DIRECTORY_READ_CONTENT))
+        {
+            // test might not fail on e.g. HttpFileSystem as there are no direcotries.
+            // A Directory do have a content on http. e.g a generated directory listing or the index.html page.
+            return;
+        }
+
+        assertTrue(folder.exists());
+
+        // Try getting the content of a folder
+        try
+        {
+            folder.getURL().openConnection().getInputStream();
+            fail();
+        }
+        catch (final IOException e)
+        {
+            assertSameMessage("vfs.provider/read-not-file.error", folder, e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlTests.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlTests.java
new file mode 100644
index 0000000..2db3276
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/UrlTests.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+
+/**
+ * URL test cases for providers.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class UrlTests
+    extends AbstractProviderTestCase
+{
+    /**
+     * Returns the capabilities required by the tests of this test case.  The
+     * tests are not run if the provider being tested does not support all
+     * the required capabilities.  Return null or an empty array to always
+     * run the tests.
+     * <p/>
+     * <p>This implementation returns null.
+     */
+    protected Capability[] getRequiredCaps()
+    {
+        return new Capability[]{Capability.URI};
+    }
+
+    /**
+     * Tests url.
+     */
+    public void testURL() throws Exception
+    {
+        final FileObject file = getReadFolder().resolveFile("some-dir/");
+        final URL url = file.getURL();
+
+        assertEquals(file.getName().getURI(), url.toExternalForm());
+
+        final URL parentURL;
+        try
+        {
+            parentURL = new URL(url, "..");
+        }
+        catch (MalformedURLException e)
+        {
+            throw e;
+        }
+        assertEquals(file.getParent().getURL(), parentURL);
+
+        final URL rootURL = new URL(url, "/");
+        assertEquals(file.getFileSystem().getRoot().getURL(), rootURL);
+    }
+
+    /**
+     * Tests content.
+     */
+    public void testURLContent() throws Exception
+    {
+        // Test non-empty file
+        FileObject file = getReadFolder().resolveFile("file1.txt");
+        assertTrue(file.exists());
+
+        URLConnection urlCon = file.getURL().openConnection();
+        assertSameURLContent(FILE1_CONTENT, urlCon);
+
+        // Test empty file
+        file = getReadFolder().resolveFile("empty.txt");
+        assertTrue(file.exists());
+
+        urlCon = file.getURL().openConnection();
+        assertSameURLContent("", urlCon);
+    }
+
+    /**
+     * Tests that unknown files have no content.
+     */
+    public void testUnknownURL() throws Exception
+    {
+        // Try getting the content of an unknown file
+        final FileObject unknownFile = getReadFolder().resolveFile("unknown-file");
+        assertFalse(unknownFile.exists());
+
+        final URLConnection connection = unknownFile.getURL().openConnection();
+        try
+        {
+            connection.getInputStream();
+            fail();
+        }
+        catch (final IOException e)
+        {
+            assertSameMessage("vfs.provider/read-not-file.error", unknownFile, e);
+        }
+        assertEquals(-1, connection.getContentLength());
+    }
+
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/VerifyingFileSelector.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/VerifyingFileSelector.java
new file mode 100644
index 0000000..a605964
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/test/VerifyingFileSelector.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.test;
+
+import junit.framework.Assert;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelectInfo;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A file selector that asserts that all files are visited, in the correct
+ * order.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class VerifyingFileSelector
+    extends Assert
+    implements FileSelector
+{
+    private final FileInfo rootFile;
+    private final List files = new ArrayList();
+
+    private FileInfo currentFolderInfo;
+    private FileObject currentFolder;
+    private Set children;
+    private List stack = new ArrayList();
+
+    public VerifyingFileSelector(final FileInfo fileInfo)
+    {
+        this.rootFile = fileInfo;
+        children = new HashSet();
+        children.add(rootFile.baseName);
+    }
+
+    /**
+     * Determines if a file or folder should be selected.
+     */
+    public boolean includeFile(final FileSelectInfo fileInfo)
+        throws FileSystemException
+    {
+        final FileObject file = fileInfo.getFile();
+        if (file == currentFolder)
+        {
+            // Pop current folder
+            assertEquals(0, children.size());
+            currentFolder = currentFolder.getParent();
+            currentFolderInfo = currentFolderInfo.getParent();
+            children = (Set) stack.remove(0);
+        }
+
+        final String baseName = file.getName().getBaseName();
+
+        final FileInfo childInfo = getChild(baseName);
+        assertSame(childInfo.type, file.getType());
+
+        final boolean isChild = children.remove(baseName);
+        assertTrue(isChild);
+
+        files.add(file);
+        return true;
+    }
+
+    /**
+     * Determines whether a folder should be traversed.
+     */
+    public boolean traverseDescendents(final FileSelectInfo fileInfo)
+        throws FileSystemException
+    {
+        // Check that the given file is a folder
+        final FileObject folder = fileInfo.getFile();
+        assertSame(FileType.FOLDER, folder.getType());
+
+        // Locate the info for the folder
+        final String baseName = folder.getName().getBaseName();
+        if (currentFolder == null)
+        {
+            assertEquals(rootFile.baseName, baseName);
+            currentFolderInfo = rootFile;
+        }
+        else
+        {
+            assertSame(currentFolder, folder.getParent());
+
+            // Locate the info for the child, and make sure it is folder
+            currentFolderInfo = getChild(baseName);
+            assertSame(FileType.FOLDER, currentFolderInfo.type);
+        }
+
+        // Push the folder
+        stack.add(0, children);
+        children = new HashSet(currentFolderInfo.children.keySet());
+        currentFolder = folder;
+
+        return true;
+    }
+
+    /**
+     * Finds a child of the current folder.
+     */
+    private FileInfo getChild(final String baseName)
+    {
+        if (currentFolderInfo == null)
+        {
+            assertEquals(rootFile.baseName, baseName);
+            return rootFile;
+        }
+        else
+        {
+            final FileInfo child = (FileInfo) currentFolderInfo.children.get(baseName);
+            assertNotNull("Could not locate child " + baseName, child);
+            return child;
+        }
+    }
+
+    /**
+     * Asserts that the selector has seen all the files.
+     *
+     * @return The files in the order they where visited.
+     */
+    public List finish()
+    {
+        assertEquals(0, children.size());
+        return files;
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilderTest.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilderTest.java
new file mode 100644
index 0000000..00f41ca
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/DelegatingFileSystemOptionsBuilderTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import junit.framework.TestCase;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.impl.StandardFileSystemManager;
+import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
+import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
+import org.apache.commons.vfs.provider.sftp.TrustEveryoneUserInfo;
+
+import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Some tests for the DelegatingFileSystemOptionsBuilder
+ * 
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+public class DelegatingFileSystemOptionsBuilderTest extends TestCase
+{
+    private StandardFileSystemManager fsm = null;
+
+    protected void setUp() throws Exception
+    {
+        super.setUp();
+
+        // get a full blown, fully functional manager
+        fsm = new StandardFileSystemManager();
+        fsm.init();
+    }
+
+
+    protected void tearDown() throws Exception
+    {
+        if (fsm != null)
+        {
+            fsm.close();
+        }
+
+        super.tearDown();
+    }
+
+    public void testDelegatingGood() throws Throwable
+    {
+        final String[] identityPaths = new String[]
+        {
+            "/file1",
+            "/file2",
+        };
+
+        FileSystemOptions opts = new FileSystemOptions();
+        DelegatingFileSystemOptionsBuilder delgate = new DelegatingFileSystemOptionsBuilder(fsm);
+
+        delgate.setConfigString(opts, "http", "proxyHost", "proxy");
+        delgate.setConfigString(opts, "http", "proxyPort", "8080");
+        delgate.setConfigClass(opts, "sftp", "userinfo", TrustEveryoneUserInfo.class);
+        delgate.setConfigStrings(opts, "sftp", "identities", identityPaths);
+
+        assertEquals("http.proxyHost", HttpFileSystemConfigBuilder.getInstance().getProxyHost(opts), "proxy");
+        assertEquals("http.proxyPort", HttpFileSystemConfigBuilder.getInstance().getProxyPort(opts), 8080);
+        assertEquals("sftp.userInfo", SftpFileSystemConfigBuilder.getInstance().getUserInfo(opts).getClass(), TrustEveryoneUserInfo.class);
+
+        File identities[] = SftpFileSystemConfigBuilder.getInstance().getIdentities(opts);
+        assertNotNull("sftp.identities", identities);
+        assertEquals("sftp.identities size", identities.length, identityPaths.length);
+        for (int iterIdentities = 0; iterIdentities < identities.length; iterIdentities++)
+        {
+            assertEquals("sftp.identities #" + iterIdentities,
+                identities[iterIdentities].getAbsolutePath(),
+                new File(identityPaths[iterIdentities]).getAbsolutePath());
+        }
+    }
+
+    public void testDelegatingBad() throws Throwable
+    {
+        FileSystemOptions opts = new FileSystemOptions();
+        DelegatingFileSystemOptionsBuilder delgate = new DelegatingFileSystemOptionsBuilder(fsm);
+
+        try
+        {
+            delgate.setConfigString(opts, "http", "proxyPort", "wrong_port");
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+            assertEquals(e.getCause().getClass(), InvocationTargetException.class);
+            assertEquals(((InvocationTargetException) e.getCause()).getTargetException().getClass(), NumberFormatException.class);
+        }
+
+        try
+        {
+            delgate.setConfigClass(opts, "sftp", "userinfo", String.class);
+            fail();
+        }
+        catch (FileSystemException e)
+        {
+            assertEquals(e.getCode(), "vfs.provider/config-value-invalid.error");
+        }
+    }
+
+    private static String[] schemes = new String[]
+    {
+        "webdav", "http", "ftp", "file", "zip", "tar", "tgz", "bz2", "gz", "jar", "tmp", "ram"
+    };
+
+    public void testConfiguration() throws Exception
+    {
+        for (int i=0; i < schemes.length; ++i)
+        {
+            assertTrue("Missing" + schemes[i] + " provider", fsm.hasProvider(schemes[i]));
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/EncryptDecryptTest.java b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/EncryptDecryptTest.java
new file mode 100644
index 0000000..45587f7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/java/org/apache/commons/vfs/util/EncryptDecryptTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ */
+public class EncryptDecryptTest extends TestCase
+{
+
+    public void testEncryptDecrypt() throws Exception
+    {
+        String source = "Qryp2!t&tpR59";
+        String expected = "914589F049CE3E8E3BB1A41BEAE12A9C";
+
+        Cryptor cryptor = CryptorFactory.getCryptor();
+        String encrypted = cryptor.encrypt(source);
+        assertEquals(expected, encrypted);
+
+        String decrypted = cryptor.decrypt(encrypted);
+        assertEquals(source, decrypted);
+
+    }
+}
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/nested.jar b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.jar
new file mode 100644
index 0000000..d7bedde
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.jar
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tar b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tar
new file mode 100644
index 0000000..937fc96
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tar
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tbz2 b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tbz2
new file mode 100644
index 0000000..6dcc77a
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tbz2
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tgz b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tgz
new file mode 100644
index 0000000..99aeacd
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.tgz
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/nested.zip b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.zip
new file mode 100644
index 0000000..a7a358c
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/nested.zip
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file1.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file1.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file1.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file2.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file2.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file2.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file3.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file3.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/file3.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file1.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file1.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file1.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file2.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file2.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file2.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file3.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file3.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir1/file3.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file1.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file1.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file1.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file2.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file2.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file2.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file3.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file3.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir2/file3.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file1.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file1.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file1.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file2.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file2.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file2.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file3.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file3.txt
new file mode 100644
index 0000000..9ad7b1b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/dir1/subdir3/file3.txt
@@ -0,0 +1 @@
+A test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/empty.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/empty.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/empty.txt
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file space.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file space.txt
new file mode 100644
index 0000000..af27ff4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file space.txt
@@ -0,0 +1 @@
+This is a test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file%.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file%.txt
new file mode 100644
index 0000000..af27ff4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file%.txt
@@ -0,0 +1 @@
+This is a test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file1.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file1.txt
new file mode 100644
index 0000000..af27ff4
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/read-tests/file1.txt
@@ -0,0 +1 @@
+This is a test file.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.jar b/VFS-2.0-RC1/core/src/test/resources/test-data/test.jar
new file mode 100644
index 0000000..1055a2b
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.jar
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.mf b/VFS-2.0-RC1/core/src/test/resources/test-data/test.mf
new file mode 100644
index 0000000..e85d462
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.mf
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Specification-Title: SpecTitle
+Specification-Vendor: SpecVendor
+Specification-Version: 1.0
+Implementation-Title: ImplTitle
+Implementation-Vendor: ImplVendor
+Implementation-Version: 1.1
+Sealed: false
+
+Name: code/sealed/
+Sealed: true
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.policy b/VFS-2.0-RC1/core/src/test/resources/test-data/test.policy
new file mode 100644
index 0000000..d5b5807
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.policy
@@ -0,0 +1,69 @@
+
+// Standard extensions get all permissions by default
+
+grant codeBase "file:${java.home}/lib/ext/*" {
+	permission java.security.AllPermission;
+};
+
+grant codeBase "file:${maven.home}/-" {
+	permission java.security.AllPermission;
+};
+
+grant codeBase "file:${maven.build.dest}" {
+    permission java.io.FilePermission "${user.dir}/vfs_cache/-", "read, write, delete";
+    permission java.io.FilePermission "${user.dir}/vfs_cache", "read, write, delete";
+    permission java.io.FilePermission "${user.dir}", "read";
+    permission java.net.NetPermission "specifyStreamHandler";
+};
+
+// default permissions granted to all domains
+
+grant { 
+    permission java.io.FilePermission "${test.basedir}/write-tests", "read, write, delete";
+    permission java.io.FilePermission "${test.basedir}/write-tests/-", "read, write, delete";
+    permission java.io.FilePermission "${test.basedir}/-", "read";
+    permission java.io.FilePermission "${test.basedir}", "read";
+
+    //This is needed for the ClassLoader tests.
+    permission java.lang.RuntimePermission "createClassLoader";
+
+	// Allows any thread to stop itself using the java.lang.Thread.stop()
+	// method that takes no argument.
+	// Note that this permission is granted by default only to remain
+	// backwards compatible.
+	// It is strongly recommended that you either remove this permission
+	// from this policy file or further restrict it to code sources
+	// that you specify, because Thread.stop() is potentially unsafe.
+	// See "http://java.sun.com/notes" for more information.
+	permission java.lang.RuntimePermission "stopThread";
+
+	// allows anyone to listen on un-privileged ports
+	permission java.net.SocketPermission "localhost:1024-", "listen";
+
+	// "standard" properies that can be read by anyone
+
+	permission java.util.PropertyPermission "java.version", "read";
+	permission java.util.PropertyPermission "java.vendor", "read";
+	permission java.util.PropertyPermission "java.vendor.url", "read";
+	permission java.util.PropertyPermission "java.class.version", "read";
+	permission java.util.PropertyPermission "os.name", "read";
+	permission java.util.PropertyPermission "os.version", "read";
+	permission java.util.PropertyPermission "os.arch", "read";
+	permission java.util.PropertyPermission "file.separator", "read";
+	permission java.util.PropertyPermission "path.separator", "read";
+	permission java.util.PropertyPermission "line.separator", "read";
+
+	permission java.util.PropertyPermission "java.specification.version", "read";
+	permission java.util.PropertyPermission "java.specification.vendor", "read";
+	permission java.util.PropertyPermission "java.specification.name", "read";
+
+	permission java.util.PropertyPermission "java.vm.specification.version", "read";
+	permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
+	permission java.util.PropertyPermission "java.vm.specification.name", "read";
+	permission java.util.PropertyPermission "java.vm.version", "read";
+	permission java.util.PropertyPermission "java.vm.vendor", "read";
+	permission java.util.PropertyPermission "java.vm.name", "read";
+	permission java.util.PropertyPermission "test.basedir", "read";
+	permission java.util.PropertyPermission "user.dir", "read";
+};
+
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.tar b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tar
new file mode 100644
index 0000000..76655b9
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tar
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.tbz2 b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tbz2
new file mode 100644
index 0000000..c7eb597
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tbz2
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.tgz b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tgz
new file mode 100644
index 0000000..218a6b1
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.tgz
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/test.zip b/VFS-2.0-RC1/core/src/test/resources/test-data/test.zip
new file mode 100644
index 0000000..6f4da24
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/test.zip
Binary files differ
diff --git a/VFS-2.0-RC1/core/src/test/resources/test-data/write-tests/dummy.txt b/VFS-2.0-RC1/core/src/test/resources/test-data/write-tests/dummy.txt
new file mode 100644
index 0000000..d7716a7
--- /dev/null
+++ b/VFS-2.0-RC1/core/src/test/resources/test-data/write-tests/dummy.txt
@@ -0,0 +1 @@
+dummy file to cause directory to be created.
\ No newline at end of file
diff --git a/VFS-2.0-RC1/doap_vfs.rdf b/VFS-2.0-RC1/doap_vfs.rdf
new file mode 100644
index 0000000..a1524d0
--- /dev/null
+++ b/VFS-2.0-RC1/doap_vfs.rdf
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+  
+        http://www.apache.org/licenses/LICENSE-2.0
+  
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+<rdf:RDF xmlns="http://usefulinc.com/ns/doap#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:asfext="http://projects.apache.org/ns/asfext#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:doap="http://usefulinc.com/ns/doap#" xml:lang="en">
+  <Project rdf:about="http://commons.apache.org/vfs/">
+    <name>Apache Commons VFS</name>
+    <homepage rdf:resource="http://commons.apache.org/vfs/"/>
+    <programming-language>Java</programming-language>
+    <category rdf:resource="http://projects.apache.org/category/library"/>
+    <license rdf:resource="http://usefulinc.com/doap/licenses/asl20"/>
+    <bug-database rdf:resource="http://issues.apache.org/jira/browse/VFS"/>
+    <download-page rdf:resource="http://commons.apache.org/vfs/download_vfs.cgi"/>
+    <asfext:pmc rdf:resource="http://commons.apache.org/"/>
+    <shortdesc xml:lang="en">Commons VFS</shortdesc>
+    <description xml:lang="en">
+        VFS is a Virtual File System library.
+    </description>
+    <repository>
+      <SVNRepository>
+        <browse rdf:resource="http://svn.apache.org/viewvc"/>
+        <location rdf:resource="http://svn.apache.org/repos/asf/commons/proper/vfs"/>
+      </SVNRepository>
+    </repository>
+    <!--
+    <release>
+      <Version>
+        <name>??</name>
+        <created>yyyy-mm-dd</created>
+        <revision>??</revision>
+      </Version>
+    </release>
+    -->
+    <mailing-list rdf:resource="http://commons.apache.org/mail-lists.html"/>
+  </Project>
+</rdf:RDF>
diff --git a/VFS-2.0-RC1/examples/pom.xml b/VFS-2.0-RC1/examples/pom.xml
new file mode 100644
index 0000000..dbf1930
--- /dev/null
+++ b/VFS-2.0-RC1/examples/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+  
+        http://www.apache.org/licenses/LICENSE-2.0
+  
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Commons VFS Examples</name>
+  <groupId>org.apache.commons</groupId>
+  <artifactId>commons-vfs-examples</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <description>VFS is a Virtual File System library - Examples.</description>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-vfs-project</artifactId>
+    <version>2.0-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-vfs</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-net</groupId>
+      <artifactId>commons-net</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.jdom</groupId>
+      <artifactId>jdom</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>com.jcraft</groupId>
+      <artifactId>jsch</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>xml-apis</groupId>
+      <artifactId>xml-apis</artifactId>
+      <optional>true</optional>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <commons.componentid>vfs-examples</commons.componentid>
+    <vfs.parent.dir>${basedir}/..</vfs.parent.dir>
+  </properties> 
+
+  <build>
+    <resources>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE.txt</include>
+        </includes>
+      </resource>
+    </resources>
+  </build>
+
+</project>
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ChangeLastModificationTime.java b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ChangeLastModificationTime.java
new file mode 100644
index 0000000..dc762ee
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ChangeLastModificationTime.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.example;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.VFS;
+
+/**
+ * Simply changed the last modification time of the given file
+ *
+ * @author imario@apache.org
+ */
+public class ChangeLastModificationTime
+{
+    public static void main(String[] args) throws Exception
+    {
+        if (args.length == 0)
+        {
+            System.err.println("Please pass the name of a file as parameter.");
+            return;
+        }
+
+        FileObject fo = VFS.getManager().resolveFile(args[0]);
+        long setTo = System.currentTimeMillis();
+        System.err.println("set to: " + setTo);
+        fo.getContent().setLastModifiedTime(setTo);
+        System.err.println("after set: " + fo.getContent().getLastModifiedTime());
+    }
+}
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/Shell.java b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/Shell.java
new file mode 100644
index 0000000..a4767cc
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/Shell.java
@@ -0,0 +1,363 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.example;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FileUtil;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.VFS;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.StringTokenizer;
+
+/**
+ * A simple command-line shell for performing file operations.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @author Gary D. Gregory
+ * @version $Id:Shell.java 232419 2005-08-13 07:23:40 +0200 (Sa, 13 Aug 2005) imario $
+ */
+public class Shell
+{
+    private static final String CVS_ID = "$Id:Shell.java 232419 2005-08-13 07:23:40 +0200 (Sa, 13 Aug 2005) imario $";
+    private final FileSystemManager mgr;
+    private FileObject cwd;
+    private BufferedReader reader;
+
+    public static void main(final String[] args)
+    {
+        try
+        {
+            (new Shell()).go();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            System.exit(1);
+        }
+        System.exit(0);
+    }
+
+    private Shell() throws FileSystemException
+    {
+        mgr = VFS.getManager();
+        cwd = mgr.resolveFile(System.getProperty("user.dir"));
+        reader = new BufferedReader(new InputStreamReader(System.in));
+    }
+
+    private void go() throws Exception
+    {
+        System.out.println("VFS Shell [" + CVS_ID + "]");
+        while (true)
+        {
+            final String[] cmd = nextCommand();
+            if (cmd == null)
+            {
+                return;
+            }
+            if (cmd.length == 0)
+            {
+                continue;
+            }
+            final String cmdName = cmd[0];
+            if (cmdName.equalsIgnoreCase("exit") || cmdName.equalsIgnoreCase("quit"))
+            {
+                return;
+            }
+            try
+            {
+                handleCommand(cmd);
+            }
+            catch (final Exception e)
+            {
+                System.err.println("Command failed:");
+                e.printStackTrace(System.err);
+            }
+        }
+    }
+
+    /**
+     * Handles a command.
+     */
+    private void handleCommand(final String[] cmd) throws Exception
+    {
+        final String cmdName = cmd[0];
+        if (cmdName.equalsIgnoreCase("cat"))
+        {
+            cat(cmd);
+        }
+        else if (cmdName.equalsIgnoreCase("cd"))
+        {
+            cd(cmd);
+        }
+        else if (cmdName.equalsIgnoreCase("cp"))
+        {
+            cp(cmd);
+        }
+        else if (cmdName.equalsIgnoreCase("help"))
+        {
+            help();
+        }
+        else if (cmdName.equalsIgnoreCase("ls"))
+        {
+            ls(cmd);
+        }
+        else if (cmdName.equalsIgnoreCase("pwd"))
+        {
+            pwd();
+        }
+        else if (cmdName.equalsIgnoreCase("rm"))
+        {
+            rm(cmd);
+        }
+        else if (cmdName.equalsIgnoreCase("touch"))
+        {
+            touch(cmd);
+        }
+        else
+        {
+            System.err.println("Unknown command \"" + cmdName + "\".");
+        }
+    }
+
+    /**
+     * Does a 'help' command.
+     */
+    private void help()
+    {
+        System.out.println("Commands:");
+        System.out.println("cat <file>         Displays the contents of a file.");
+        System.out.println("cd [folder]        Changes current folder.");
+        System.out.println("cp <src> <dest>    Copies a file or folder.");
+        System.out.println("help               Shows this message.");
+        System.out.println("ls [-R] [path]     Lists contents of a file or folder.");
+        System.out.println("pwd                Displays current folder.");
+        System.out.println("rm <path>          Deletes a file or folder.");
+        System.out.println("touch <path>       Sets the last-modified time of a file.");
+        System.out.println("exit       Exits this program.");
+        System.out.println("quit       Exits this program.");
+    }
+
+    /**
+     * Does an 'rm' command.
+     */
+    private void rm(final String[] cmd) throws Exception
+    {
+        if (cmd.length < 2)
+        {
+            throw new Exception("USAGE: rm <path>");
+        }
+
+        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
+        file.delete(Selectors.SELECT_SELF);
+    }
+
+    /**
+     * Does a 'cp' command.
+     */
+    private void cp(final String[] cmd) throws Exception
+    {
+        if (cmd.length < 3)
+        {
+            throw new Exception("USAGE: cp <src> <dest>");
+        }
+
+        final FileObject src = mgr.resolveFile(cwd, cmd[1]);
+        FileObject dest = mgr.resolveFile(cwd, cmd[2]);
+        if (dest.exists() && dest.getType() == FileType.FOLDER)
+        {
+            dest = dest.resolveFile(src.getName().getBaseName());
+        }
+
+        dest.copyFrom(src, Selectors.SELECT_ALL);
+    }
+
+    /**
+     * Does a 'cat' command.
+     */
+    private void cat(final String[] cmd) throws Exception
+    {
+        if (cmd.length < 2)
+        {
+            throw new Exception("USAGE: cat <path>");
+        }
+
+        // Locate the file
+        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
+
+        // Dump the contents to System.out
+        FileUtil.writeContent(file, System.out);
+        System.out.println();
+    }
+
+    /**
+     * Does a 'pwd' command.
+     */
+    private void pwd()
+    {
+        System.out.println("Current folder is " + cwd.getName());
+    }
+
+    /**
+     * Does a 'cd' command.
+     * If the taget directory does not exist, a message is printed to <code>System.err</code>.
+     */
+    private void cd(final String[] cmd) throws Exception
+    {
+        final String path;
+        if (cmd.length > 1)
+        {
+            path = cmd[1];
+        }
+        else
+        {
+            path = System.getProperty("user.home");
+        }
+
+        // Locate and validate the folder
+        FileObject tmp = mgr.resolveFile(cwd, path);
+        if (tmp.exists())
+        {
+            cwd = tmp;
+        }
+        else
+        {
+            System.out.println("Folder does not exist: " + tmp.getName());
+        }
+        System.out.println("Current folder is " + cwd.getName());
+    }
+
+    /**
+     * Does an 'ls' command.
+     */
+    private void ls(final String[] cmd) throws FileSystemException
+    {
+        int pos = 1;
+        final boolean recursive;
+        if (cmd.length > pos && cmd[pos].equals("-R"))
+        {
+            recursive = true;
+            pos++;
+        }
+        else
+        {
+            recursive = false;
+        }
+
+        final FileObject file;
+        if (cmd.length > pos)
+        {
+            file = mgr.resolveFile(cwd, cmd[pos]);
+        }
+        else
+        {
+            file = cwd;
+        }
+
+        if (file.getType() == FileType.FOLDER)
+        {
+            // List the contents
+            System.out.println("Contents of " + file.getName());
+            listChildren(file, recursive, "");
+        }
+        else
+        {
+            // Stat the file
+            System.out.println(file.getName());
+            final FileContent content = file.getContent();
+            System.out.println("Size: " + content.getSize() + " bytes.");
+            final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
+            final String lastMod = dateFormat.format(new Date(content.getLastModifiedTime()));
+            System.out.println("Last modified: " + lastMod);
+        }
+    }
+
+    /**
+     * Does a 'touch' command.
+     */
+    private void touch(final String[] cmd) throws Exception
+    {
+        if (cmd.length < 2)
+        {
+            throw new Exception("USAGE: touch <path>");
+        }
+        final FileObject file = mgr.resolveFile(cwd, cmd[1]);
+        if (!file.exists())
+        {
+            file.createFile();
+        }
+        file.getContent().setLastModifiedTime(System.currentTimeMillis());
+    }
+
+    /**
+     * Lists the children of a folder.
+     */
+    private void listChildren(final FileObject dir,
+                              final boolean recursive,
+                              final String prefix)
+        throws FileSystemException
+    {
+        final FileObject[] children = dir.getChildren();
+        for (int i = 0; i < children.length; i++)
+        {
+            final FileObject child = children[i];
+            System.out.print(prefix);
+            System.out.print(child.getName().getBaseName());
+            if (child.getType() == FileType.FOLDER)
+            {
+                System.out.println("/");
+                if (recursive)
+                {
+                    listChildren(child, recursive, prefix + "    ");
+                }
+            }
+            else
+            {
+                System.out.println();
+            }
+        }
+    }
+
+    /**
+     * Returns the next command, split into tokens.
+     */
+    private String[] nextCommand() throws IOException
+    {
+        System.out.print("> ");
+        final String line = reader.readLine();
+        if (line == null)
+        {
+            return null;
+        }
+        final ArrayList cmd = new ArrayList();
+        final StringTokenizer tokens = new StringTokenizer(line);
+        while (tokens.hasMoreTokens())
+        {
+            cmd.add(tokens.nextToken());
+        }
+        return (String[]) cmd.toArray(new String[cmd.size()]);
+    }
+}
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ShowProperties.java b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ShowProperties.java
new file mode 100644
index 0000000..b7565c4
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/ShowProperties.java
@@ -0,0 +1,102 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.example;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.VFS;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * A simple that prints the properties of the file passed as first parameter.
+ *
+ * @author <a href="mailto:anthony@antcommander.com">Anthony Goubard</a>
+ * @version $Revision:232419 $ $Date:2005-08-13 07:23:40 +0200 (Sa, 13 Aug 2005) $
+ */
+
+
+public class ShowProperties
+{
+    public static void main(String[] args)
+    {
+        if (args.length == 0)
+        {
+            System.err.println("Please pass the name of a file as parameter.");
+            System.err.println("e.g. java org.apache.commons.vfs.example.ShowProperties LICENSE.txt");
+            return;
+        }
+        for (int i = 0; i < args.length; i++)
+        {
+            try
+            {
+                FileSystemManager mgr = VFS.getManager();
+                System.out.println();
+                System.out.println("Parsing: " + args[i]);
+                FileObject file = mgr.resolveFile(args[i]);
+                System.out.println("URL: " + file.getURL());
+                System.out.println("getName(): " + file.getName());
+                System.out.println("BaseName: " + file.getName().getBaseName());
+                System.out.println("Extension: " + file.getName().getExtension());
+                System.out.println("Path: " + file.getName().getPath());
+                System.out.println("Scheme: " + file.getName().getScheme());
+                System.out.println("URI: " + file.getName().getURI());
+                System.out.println("Root URI: " + file.getName().getRootURI());
+                System.out.println("Parent: " + file.getName().getParent());
+                System.out.println("Type: " + file.getType());
+                System.out.println("Exists: " + file.exists());
+                System.out.println("Readable: " + file.isReadable());
+                System.out.println("Writeable: " + file.isWriteable());
+                System.out.println("Root path: " + file.getFileSystem().getRoot().getName().getPath());
+                if (file.exists())
+                {
+                    if (file.getType().equals(FileType.FILE))
+                    {
+                        System.out.println("Size: " + file.getContent().getSize() + " bytes");
+                    }
+                    else if (file.getType().equals(FileType.FOLDER) && file.isReadable())
+                    {
+                        FileObject[] children = file.getChildren();
+                        System.out.println("Directory with " + children.length + " files");
+                        for (int iterChildren = 0; iterChildren < children.length; iterChildren++)
+                        {
+                            System.out.println("#" + iterChildren + ": " + children[iterChildren].getName());
+                            if (iterChildren > 5)
+                            {
+                                break;
+                            }
+                        }
+                    }
+                    System.out.println("Last modified: " + DateFormat.getInstance().format(new Date(file.getContent().getLastModifiedTime())));
+                }
+                else
+                {
+                    System.out.println("The file does not exist");
+                }
+                file.close();
+            }
+            catch (FileSystemException ex)
+            {
+                ex.printStackTrace();
+            }
+        }
+    }
+}
+
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/package.html b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/package.html
new file mode 100644
index 0000000..85b1016
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/example/package.html
@@ -0,0 +1,19 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<body>
+<p>Examples classes.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/FtpCheck.java b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/FtpCheck.java
new file mode 100644
index 0000000..427858f
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/FtpCheck.java
@@ -0,0 +1,94 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.libcheck;
+
+import org.apache.commons.net.ftp.FTPClient;
+import org.apache.commons.net.ftp.FTPFile;
+import org.apache.commons.net.ftp.FTPReply;
+
+import java.io.OutputStream;
+
+/**
+ * Basic check for sftp
+ */
+public class FtpCheck
+{
+    public static void main(String args[]) throws Exception
+    {
+        if (args.length < 3)
+        {
+            throw new IllegalArgumentException("Usage: FtpCheck user pass host dir");
+        }
+        String user = args[0];
+        String pass = args[1];
+        String host = args[2];
+        String dir = null;
+        if (args.length == 4)
+        {
+            dir = args[3];
+        }
+
+        FTPClient client = new FTPClient();
+        client.connect(host);
+        int reply = client.getReplyCode();
+        if (!FTPReply.isPositiveCompletion(reply))
+        {
+            throw new IllegalArgumentException("cant connect: " + reply);
+        }
+        if (!client.login(user, pass))
+        {
+            throw new IllegalArgumentException("login failed");
+        }
+        client.enterLocalPassiveMode();
+
+        OutputStream os = client.storeFileStream(dir + "/test.txt");
+        if (os == null)
+        {
+            throw new IllegalStateException(client.getReplyString());
+        }
+        os.write("test".getBytes());
+        os.close();
+        client.completePendingCommand();
+
+        if (dir != null)
+        {
+            if (!client.changeWorkingDirectory(dir))
+            {
+                throw new IllegalArgumentException("change dir to '" + dir + "' failed");
+            }
+        }
+
+        System.err.println("System: " + client.getSystemName());
+
+        FTPFile[] files = client.listFiles();
+        for (int i = 0; i < files.length; i++)
+        {
+            FTPFile file = files[i];
+            if (file == null)
+            {
+                System.err.println("#" + i + ": " + null);
+            }
+            else
+            {
+                System.err.println("#" + i + ": " + file.getRawListing());
+                System.err.println("#" + i + ": " + file.toString());
+                System.err.println("\t name:" + file.getName() + " type:" + file.getType());
+            }
+        }
+        client.disconnect();
+    }
+}
diff --git a/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/SftpCheck.java b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/SftpCheck.java
new file mode 100644
index 0000000..6b2aa16
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/main/java/org/apache/commons/vfs/libcheck/SftpCheck.java
@@ -0,0 +1,93 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.libcheck;
+
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Basic check for sftp
+ */
+public class SftpCheck
+{
+    public static void main(String args[]) throws Exception
+    {
+        if (args.length != 4)
+        {
+            throw new IllegalArgumentException("Usage: SftpCheck user pass host dir");
+        }
+        String user = args[0];
+        String pass = args[1];
+        String host = args[2];
+        String dir = args[3];
+
+        Properties props = new Properties();
+        props.setProperty("StrictHostKeyChecking", "false");
+        JSch jsch = new JSch();
+        Session session = jsch.getSession(user, host, 22);
+        session.setUserInfo(new UserInfo()
+        {
+            public String getPassphrase()
+            {
+                return null;
+            }
+
+            public String getPassword()
+            {
+                return null;
+            }
+
+            public boolean promptPassword(String string)
+            {
+                return false;
+            }
+
+            public boolean promptPassphrase(String string)
+            {
+                return false;
+            }
+
+            public boolean promptYesNo(String string)
+            {
+                return true;
+            }
+
+            public void showMessage(String string)
+            {
+            }
+        });
+        session.setPassword(pass);
+        session.connect();
+        ChannelSftp chan = (ChannelSftp) session.openChannel("sftp");
+        chan.connect();
+        Vector list = chan.ls(dir);
+        Iterator iterList = list.iterator();
+        while (iterList.hasNext())
+        {
+            System.err.println(iterList.next());
+        }
+        System.err.println("done");
+        chan.disconnect();
+        session.disconnect();
+    }
+}
diff --git a/VFS-2.0-RC1/examples/src/site/site.xml b/VFS-2.0-RC1/examples/src/site/site.xml
new file mode 100644
index 0000000..61d4cb2
--- /dev/null
+++ b/VFS-2.0-RC1/examples/src/site/site.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Commons&#xA0;VFS">
+
+  <bannerRight>
+    <name>Commons&#xA0;VFS</name>
+    <src>../images/vfs-logo-white.png</src>
+    <href>../index.html</href>
+  </bannerRight>
+
+  <body>
+    <links>
+      <item name="Commons VFS Home" href="../index.html"/>
+    </links>
+
+    <menu name="Commons&#xA0;VFS">
+      <item name="Overview"                href="../index.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/VFS-2.0-RC1/findbugs-exclude-filter.xml b/VFS-2.0-RC1/findbugs-exclude-filter.xml
new file mode 100644
index 0000000..873d353
--- /dev/null
+++ b/VFS-2.0-RC1/findbugs-exclude-filter.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+
+<!-- ===================================================================== -->
+<!-- $Id$ -->
+<!-- ===================================================================== -->
+<FindBugsFilter>
+  <!-- Enable only high priority warnings -->
+  <Match>
+    <Priority value="2"/>
+  </Match>
+
+  <Match>
+    <Priority value="3"/>
+  </Match>
+</FindBugsFilter>
diff --git a/VFS-2.0-RC1/pom.xml b/VFS-2.0-RC1/pom.xml
new file mode 100644
index 0000000..1199654
--- /dev/null
+++ b/VFS-2.0-RC1/pom.xml
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-parent</artifactId>
+    <version>17</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.commons</groupId>
+  <artifactId>commons-vfs-project</artifactId>
+  <name>Commons VFS</name>
+  <description>VFS is a Virtual File System library.</description>
+  <packaging>pom</packaging>
+  <version>2.0-SNAPSHOT</version>
+
+  <url>http://commons.apache.org/vfs/</url>
+  <inceptionYear>2002</inceptionYear>
+
+  <modules>
+    <module>core</module>
+    <module>examples</module>
+    <module>sandbox</module>
+  </modules>
+
+  <issueManagement>
+    <system>jira</system>
+    <url>https://issues.apache.org/jira/browse/VFS</url>
+  </issueManagement>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/commons/proper/vfs/trunk</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/commons/proper/vfs/trunk</developerConnection>
+    <url>http://svn.apache.org/viewvc/commons/proper/vfs/trunk/</url>
+  </scm>
+
+  <developers>
+    <developer>
+      <name>Adam Murdoch</name>
+      <id>adammurdoch</id>
+      <email>adammurdoch -at- apache.org</email>
+      <organization></organization>
+    </developer>
+    <developer>
+      <name>James Strachan</name>
+      <id>jstrachan</id>
+      <email>jstrachan -at- apache.org</email>
+      <organization>SpiritSoft, Inc.</organization>
+    </developer>
+    <developer>
+      <name>Mario Ivankovits</name>
+      <id>imario</id>
+      <email>imario -at- apache.org</email>
+      <organization>OPS EDV Gmbh</organization>
+    </developer>
+    <developer>
+      <name>Rahul Akolkar</name>
+      <id>rahul</id>
+      <email>rahul -at- apache.org</email>
+      <organization>Apache Software Foundation</organization>
+    </developer>
+    <developer>
+      <name>James Carman</name>
+      <id>jcarman</id>
+      <email>jcarman -at- apache.org</email>
+      <organization>Apache Software Foundation</organization>
+    </developer>
+    <developer>
+      <name>Ralph Goers</name>
+      <id>rgoers</id>
+      <email>rgoers -at- apache.org</email>
+      <organization>Intuit</organization>
+    </developer>
+    <developer>
+      <name>Joerg Schaible</name>
+      <id>joehni</id>
+      <email>joehni -at- apache.org</email>
+    </developer>
+   </developers>
+
+  <contributors>
+    <contributor>
+      <name>Rami Ojares</name>
+      <email>rami.ojares -at- elisa.fi</email>
+    </contributor>
+    <contributor>
+      <name>Anthony Goubard</name>
+      <email>adagoubard -at- chello.nl</email>
+    </contributor>
+    <contributor>
+      <name>Christopher Ottley</name>
+      <email>xknight -at- users.sourceforge.net</email>
+    </contributor>
+  </contributors>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <commons.componentid>vfs</commons.componentid>
+    <commons.release.version>1.0</commons.release.version>
+    <commons.binary.suffix></commons.binary.suffix>
+    <commons.jira.id>VFS</commons.jira.id>
+    <commons.jira.pid>12310495</commons.jira.pid>
+    <maven.compile.source>1.4</maven.compile.source>
+    <maven.compile.target>1.4</maven.compile.target>
+    <commons.release.name>commons-vfs-${commons.release.version}</commons.release.name>
+    <vfs.parent.dir>${basedir}</vfs.parent.dir>
+  </properties>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-checkstyle-plugin</artifactId>
+          <version>2.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-site-plugin</artifactId>
+          <version>2.1.1</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-build-plugin</artifactId>
+        <!-- version inherited from commons-parent -->
+        <configuration>
+            <commons.release.name>commons-${commons.componentid}-${commons.release.version}</commons.release.name>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-assembly-plugin</artifactId>
+        <!-- version inherited from commons-parent -->
+        <configuration>
+          <descriptors>
+            <descriptor>src/assembly/bin.xml</descriptor>
+            <descriptor>src/assembly/src.xml</descriptor>
+          </descriptors>
+          <tarLongFileMode>gnu</tarLongFileMode>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <!-- version inherited from commons-parent -->
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <phase>install</phase>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.1</version>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>2.0</version>
+        <configuration>
+          <xmlPath>${basedir}/src/changes/changes.xml</xmlPath>
+          <issueLinkTemplate>%URL%/%ISSUE%</issueLinkTemplate>
+        </configuration>
+        <reportSets>
+          <reportSet>
+            <reports>
+               <report>changes-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>2.2</version>
+        <configuration>
+          <!--<propertiesLocation>${vfs.parent.dir}/checkstyle.properties</propertiesLocation> -->
+          <configLocation>${vfs.parent.dir}/checkstyle.xml</configLocation>
+          <suppressionsLocation>${vfs.parent.dir}/checkstyle-suppressions.xml</suppressionsLocation>
+          <enableRulesSummary>false</enableRulesSummary>
+          <propertyExpansion>basedir=${basedir}</propertyExpansion>
+          <propertyExpansion>licensedir=${vfs.parent.dir}/checkstyle-header.txt</propertyExpansion>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>2.1</version>
+        <configuration>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.5</version>
+        <configuration>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>1.0.0</version>
+        <configuration>
+          <threshold>Normal</threshold>
+          <effort>Default</effort>
+          <excludeFilterFile>findbugs-exclude-filter.xml</excludeFilterFile>
+       </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-site-plugin</artifactId>
+        <version>2.1.1</version>
+        <configuration>
+          <moduleExcludes>
+            <xdoc>navigation.xml,changes.xml</xdoc>
+          </moduleExcludes>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+
+  <dependencyManagement>
+    <dependencies>
+      <!-- artifacts of project, versions managed by release-plugin -->
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-vfs</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-vfs</artifactId>
+        <version>${project.version}</version>
+        <type>test-jar</type>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-vfs-sandbox</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-vfs-examples</artifactId>
+        <version>${project.version}</version>
+      </dependency>
+
+      <!-- 3rd party dependencies -->
+      <dependency>
+        <groupId>commons-logging</groupId>
+        <artifactId>commons-logging</artifactId>
+        <version>1.1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-net</groupId>
+        <artifactId>commons-net</artifactId>
+        <version>2.0</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>3.1</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-httpclient</groupId>
+        <artifactId>commons-httpclient</artifactId>
+        <version>3.0</version>
+        <!-- JCR-683: Exclude bad transitive dependencies, check again when upgrading version -->
+        <exclusions>
+          <exclusion>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+          </exclusion>
+        </exclusions>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.commons</groupId>
+        <artifactId>commons-compress</artifactId>
+        <version>1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.jackrabbit</groupId>
+        <artifactId>jackrabbit-webdav</artifactId>
+        <version>1.5.2</version>
+      </dependency>
+      <dependency>
+        <groupId>ant</groupId>
+        <artifactId>ant</artifactId>
+        <version>1.6.2</version>
+      </dependency>
+      <dependency>
+        <groupId>xml-apis</groupId>
+        <artifactId>xml-apis</artifactId>
+        <version>1.0.b2</version>
+      </dependency>
+      <dependency>
+        <groupId>org.jdom</groupId>
+        <artifactId>jdom</artifactId>
+        <version>1.1</version>
+      </dependency>
+      <dependency>
+        <groupId>com.jcraft</groupId>
+        <artifactId>jsch</artifactId>
+        <version>0.1.42</version>
+      </dependency>
+      <dependency>
+        <groupId>jcifs</groupId>
+        <artifactId>jcifs</artifactId>
+        <version>0.8.3</version>
+      </dependency>
+      <dependency>
+        <groupId>javax.mail</groupId>
+        <artifactId>mail</artifactId>
+        <version>1.4</version>
+      </dependency>
+      <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>3.8.2</version>
+        <scope>test</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <repositories>
+    <repository>
+      <id>apache.snapshots.https</id>
+      <name>Apache Snapshot Repository</name>
+      <url>https://repository.apache.org/content/repositories/snapshots</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+    </repository>
+    <repository>
+      <id>apache.snapshots</id>
+      <name>Apache Snapshot Repository</name>
+      <url>http://people.apache.org/repo/m2-snapshot-repository/</url>
+      <releases>
+        <enabled>false</enabled>
+      </releases>
+    </repository>
+    <repository>
+      <id>apache.m1</id>
+      <name>Apache Maven 1 Repository</name>
+      <url>http://people.apache.org/repo/m1-snapshot-repository/</url>
+      <layout>legacy</layout>
+    </repository>
+  </repositories>
+
+  <distributionManagement>
+    <repository>
+      <id>apache.releases.https</id>
+      <name>Apache Release Distribution Repository</name>
+      <url>https://repository.apache.org/service/local/staging/deploy/maven2</url>
+    </repository>
+    <snapshotRepository>
+      <id>apache.snapshots.https</id>
+      <name>Apache Development Snapshot Repository</name>
+      <url>https://repository.apache.org/content/repositories/snapshots</url>
+    </snapshotRepository>
+    <site>
+      <id>apache.website</id>
+      <url>scp://people.apache.org/www/commons.apache.org/vfs/</url>
+    </site>
+  </distributionManagement>
+
+</project>
diff --git a/VFS-2.0-RC1/sandbox/build.xml b/VFS-2.0-RC1/sandbox/build.xml
new file mode 100644
index 0000000..f1a7660
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/build.xml
@@ -0,0 +1,138 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+  
+        http://www.apache.org/licenses/LICENSE-2.0
+  
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+<project name="commons-vfs-sandbox" default="jar" basedir=".">
+  <property file="${user.home}/.m2/maven.properties"/>
+  <property name="maven.build.output" value="target/classes"/>
+  <property name="maven.build.directory" value="target"/>
+  <property name="maven.build.final.name" value="commons-vfs-sandbox-2.0-SNAPSHOT"/>
+  <property name="maven.test.reports" value="${maven.build.directory}/test-reports"/>
+  <property name="maven.test.output" value="target/test-classes"/>
+  <property name="maven.repo.local" value="${user.home}/.m2/repository"/>
+  <path id="build.classpath">
+    <fileset dir="${maven.repo.local}">
+      <include name="slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar"/>
+      <include name="org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar"/>
+      <include name="commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar"/>
+      <include name="javax/activation/activation/1.1/activation-1.1.jar"/>
+      <include name="javax/mail/mail/1.4/mail-1.4.jar"/>
+      <include name="commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar"/>
+      <include name="jcifs/jcifs/0.8.3/jcifs-0.8.3.jar"/>
+    </fileset>
+  </path>
+  <target name="clean" description="Clean the output directory">
+    <delete dir="${maven.build.directory}"/>
+  </target>
+  <target name="compile" depends="get-deps" description="Compile the code">
+    <mkdir dir="${maven.build.output}"/>
+    <javac destdir="${maven.build.output}" excludes="**/package.html" debug="true" deprecation="true" optimize="false">
+      <src>
+        <pathelement location="src/main/java"/>
+      </src>
+      <classpath refid="build.classpath"/>
+    </javac>
+    <mkdir dir="${maven.build.output}/META-INF"/>
+    <copy todir="${maven.build.output}/META-INF">
+      <fileset dir="..">
+        <include name="NOTICE.txt"/>
+      </fileset>
+    </copy>
+    <copy todir="${maven.build.output}">
+      <fileset dir="src/main/resources">
+        <include name="**"/>
+      </fileset>
+    </copy>
+    <copy todir="${maven.build.output}">
+      <fileset dir="..">
+        <include name="LICENSE.txt"/>
+      </fileset>
+    </copy>
+  </target>
+<!--
+  <target name="jar" depends="compile,test" description="Clean the JAR">
+-->
+  <target name="jar" depends="compile" description="Clean the JAR">
+    <jar jarfile="${maven.build.directory}/${maven.build.final.name}.jar" basedir="${maven.build.output}" excludes="**/package.html"/>
+  </target>
+  <target name="compile-tests" depends="junit-present, compile" description="Compile the test code" if="junit.present">
+    <mkdir dir="${maven.test.output}"/>
+    <javac destdir="${maven.test.output}" excludes="**/package.html" debug="true" deprecation="true" optimize="false">
+      <src>
+        <pathelement location="src/test/java"/>
+      </src>
+      <classpath>
+        <path refid="build.classpath"/>
+        <pathelement location="${maven.build.output}"/>
+      </classpath>
+    </javac>
+  </target>
+  <target name="test" depends="junit-present, compile-tests" if="junit.present" description="Run the test cases">
+    <mkdir dir="${maven.test.reports}"/>
+    <junit printSummary="yes" haltonerror="true" haltonfailure="true" fork="true" dir=".">
+      <sysproperty key="basedir" value="."/>
+      <formatter type="xml"/>
+      <formatter type="plain" usefile="false"/>
+      <classpath>
+        <path refid="build.classpath"/>
+        <pathelement location="${maven.build.output}"/>
+        <pathelement location="${maven.test.output}"/>
+      </classpath>
+      <batchtest todir="${maven.test.reports}">
+        <fileset dir="src/test/java">
+          <include name="**/*Test.java"/>
+          <exclude name="**/*Abstract*Test.java"/>
+        </fileset>
+      </batchtest>
+    </junit>
+  </target>
+  <target name="test-junit-present">
+    <available classname="junit.framework.Test" property="junit.present"/>
+  </target>
+  <target name="junit-present" depends="test-junit-present" unless="junit.present">
+    <echo>================================= WARNING ================================</echo>
+    <echo> Junit isn&apos;t present in your $ANT_HOME/lib directory. Tests not executed. </echo>
+    <echo>==========================================================================</echo>
+  </target>
+  <target name="test-offline">
+    <condition property="maven.mode.offline">
+      <equals arg1="${build.sysclasspath}" arg2="only"/>
+    </condition>
+  </target>
+  <target name="get-deps" depends="test-offline" description="Download all dependencies" unless="maven.mode.offline">
+    <mkdir dir="${maven.repo.local}"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" dest="${maven.repo.local}/slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" dest="${maven.repo.local}/slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" dest="${maven.repo.local}/slide/jakarta-slide-webdavlib/20050629.161100/jakarta-slide-webdavlib-20050629.161100.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" dest="${maven.repo.local}/org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" dest="${maven.repo.local}/org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" dest="${maven.repo.local}/org/apache/commons/commons-vfs/2.0-SNAPSHOT/commons-vfs-2.0-SNAPSHOT.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" dest="${maven.repo.local}/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" dest="${maven.repo.local}/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" dest="${maven.repo.local}/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//javax/activation/activation/1.1/activation-1.1.jar" dest="${maven.repo.local}/javax/activation/activation/1.1/activation-1.1.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//javax/activation/activation/1.1/activation-1.1.jar" dest="${maven.repo.local}/javax/activation/activation/1.1/activation-1.1.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/javax/activation/activation/1.1/activation-1.1.jar" dest="${maven.repo.local}/javax/activation/activation/1.1/activation-1.1.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//javax/mail/mail/1.4/mail-1.4.jar" dest="${maven.repo.local}/javax/mail/mail/1.4/mail-1.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//javax/mail/mail/1.4/mail-1.4.jar" dest="${maven.repo.local}/javax/mail/mail/1.4/mail-1.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/javax/mail/mail/1.4/mail-1.4.jar" dest="${maven.repo.local}/javax/mail/mail/1.4/mail-1.4.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" dest="${maven.repo.local}/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" dest="${maven.repo.local}/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" dest="${maven.repo.local}/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m2-snapshot-repository//jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" dest="${maven.repo.local}/jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://people.apache.org/repo/m1-snapshot-repository//jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" dest="${maven.repo.local}/jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" usetimestamp="true" ignoreerrors="true"/>
+    <get src="http://repo1.maven.org/maven2/jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" dest="${maven.repo.local}/jcifs/jcifs/0.8.3/jcifs-0.8.3.jar" usetimestamp="true" ignoreerrors="true"/>
+  </target>
+</project>
diff --git a/VFS-2.0-RC1/sandbox/pom.xml b/VFS-2.0-RC1/sandbox/pom.xml
new file mode 100644
index 0000000..3e39fd4
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/pom.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+  
+        http://www.apache.org/licenses/LICENSE-2.0
+  
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <name>Commons VFS Sandbox</name>
+  <groupId>org.apache.commons</groupId>
+  <artifactId>commons-vfs-sandbox</artifactId>
+  <version>2.0-SNAPSHOT</version>
+  <description>VFS is a Virtual File System library - Sandbox.</description>
+
+  <parent>
+    <groupId>org.apache.commons</groupId>
+    <artifactId>commons-vfs-project</artifactId>
+    <version>2.0-SNAPSHOT</version>
+    <relativePath>../</relativePath>
+  </parent>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-vfs</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>commons-logging</groupId>
+      <artifactId>commons-logging</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>jcifs</groupId>
+      <artifactId>jcifs</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-httpclient</groupId>
+      <artifactId>commons-httpclient</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>javax.mail</groupId>
+      <artifactId>mail</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+       <groupId>org.apache.commons</groupId>
+       <artifactId>commons-vfs</artifactId>
+       <type>test-jar</type>
+     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+  </dependencies>
+
+  <properties>
+    <commons.componentid>vfs-sandbox</commons.componentid>
+    <vfs.parent.dir>${basedir}/..</vfs.parent.dir>
+  </properties>
+
+  <build>
+    <resources>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>NOTICE.txt</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+        <includes>
+          <include>**</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>..</directory>
+        <targetPath>META-INF</targetPath>
+        <includes>
+          <include>LICENSE.txt</include>
+        </includes>
+      </resource>
+    </resources>
+    <plugins>
+      <plugin>
+        <!-- surfire do not honor suite(), see MSUREFIRE-131 why our tests wont work with maven 2 -->
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <systemProperties>
+            <property>
+              <name>test.basedir</name>
+              <value>../core/target/test-classes/test-data</value>
+            </property>
+            <property>
+              <name>test.basedir.res</name>
+              <value>test-data</value>
+            </property>
+          </systemProperties>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <profiles>
+    <profile>
+      <id>smb</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <systemProperties>
+                <property>
+                  <name>test.basedir</name>
+                  <value>../core/target/test-classes/test-data</value>
+                </property>
+                <property>
+                  <name>test.basedir.res</name>
+                  <value>test-data</value>
+                </property>
+                <property>
+                  <name>test.http.uri</name>
+                  <value>${test.smb.uri}</value>
+                </property>
+              </systemProperties>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/RACRandomAccessFile.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/RACRandomAccessFile.java
new file mode 100644
index 0000000..6f6a352
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/RACRandomAccessFile.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
+
+/**
+ * Encapsulates a {@link RandomAccessContent} instance, allowing it to be used
+ * as a {@link RandomAccessFile} instance.
+ *
+ * @author Elifarley Callado Coelho Cruz <elifarley@gmail.com>
+ * @version 1.1, $LastChangedRevision: 1163 $, $LastChangedDate: 2006-12-13 03:18:57 +0000 (Qua, 13 Dez 2006) $
+ */
+public class RACRandomAccessFile extends RandomAccessFile implements RandomAccessContent
+{
+    private RandomAccessContent rac;
+    protected final byte[] singleByteBuf = new byte[1];
+
+    private static File createTempFile() throws IOException
+    {
+        return File.createTempFile("fraf", "");
+    }
+
+    private void deleteTempFile(File tempFile)
+    {
+        try
+        {
+            super.close();
+        }
+        catch (IOException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+        finally
+        {
+            tempFile.delete();
+        }
+    }
+
+    public RACRandomAccessFile(RandomAccessContent rac) throws IOException
+    {
+        this(createTempFile());
+        this.rac = rac;
+    }
+
+    private RACRandomAccessFile(File tempFile) throws IOException
+    {
+        super(tempFile, "r");
+        deleteTempFile(tempFile);
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return this.rac.getFilePointer();
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        this.rac.seek(pos);
+    }
+
+    public int skipBytes(int n) throws IOException
+    {
+        return this.rac.skipBytes(n);
+    }
+
+    public long length() throws IOException
+    {
+        return this.rac.length();
+    }
+
+    /* (non-Javadoc)
+         * @see org.ecc.base.io.FilterRandomAccessFile#setLength(long)
+         */
+    public void setLength(long newLength) throws IOException
+    {
+        throw new IOException("Underlying RandomAccessContent instance length cannot be modified.");
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return this.rac.getInputStream();
+    }
+
+    public void close() throws IOException
+    {
+        this.rac.close();
+    }
+
+
+    /**
+     * @see java.io.RandomAccessFile#read(byte[])
+     */
+    public final int read(byte[] b) throws IOException
+    {
+        return read(b, 0, b.length);
+    }
+
+    /**
+     * @see java.io.RandomAccessFile#read()
+     */
+    public final int read() throws IOException
+    {
+        final byte[] buf = this.singleByteBuf;
+        int count = read(buf, 0, 1);
+        return count < 0 ? -1 : (buf[0] & 0xFF);
+    }
+
+    public int read(byte[] b, int off, int len) throws IOException
+    {
+        this.rac.readFully(b, off, len);
+        return len;
+    }
+
+    /**
+     * @see java.io.RandomAccessFile#write(int)
+     */
+    public final void write(int b) throws IOException
+    {
+        final byte[] buf = this.singleByteBuf;
+        buf[0] = (byte) b;
+        write(buf, 0, 1);
+    }
+
+    /**
+     * @see java.io.RandomAccessFile#write(byte[])
+     */
+    public final void write(byte[] b) throws IOException
+    {
+        write(b, 0, b.length);
+    }
+
+    /**
+     * @see java.io.RandomAccessFile#write(byte[],int,int)
+     */
+    public void write(byte[] b, int off, int len) throws IOException
+    {
+        this.rac.write(b, off, len);
+    }
+
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeAttributesMap.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeAttributesMap.java
new file mode 100644
index 0000000..b3f5260
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeAttributesMap.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.mime;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import javax.mail.Header;
+import javax.mail.MessagingException;
+import javax.mail.Part;
+import javax.mail.Address;
+import javax.mail.internet.MimeMessage;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * A map which tries to allow access to the various aspects of the mail
+ */
+public class MimeAttributesMap implements Map
+{
+    private Log log = LogFactory.getLog(MimeAttributesMap.class);
+
+    private final static String OBJECT_PREFIX = "obj.";
+
+    private final Part part;
+    private Map backingMap;
+
+    private final Map mimeMessageGetters = new TreeMap();
+
+    public MimeAttributesMap(Part part)
+    {
+        this.part = part;
+        addMimeMessageMethod(part.getClass().getMethods());
+        addMimeMessageMethod(part.getClass().getDeclaredMethods());
+    }
+
+    private void addMimeMessageMethod(Method[] methods)
+    {
+        for (int i = 0; i < methods.length; i++)
+        {
+            Method method = methods[i];
+            if (!Modifier.isPublic(method.getModifiers()))
+            {
+                continue;
+            }
+            if (method.getParameterTypes().length > 0)
+            {
+                continue;
+            }
+
+            if (method.getName().startsWith("get"))
+            {
+                mimeMessageGetters.put(method.getName().substring(3), method);
+            }
+            else if (method.getName().startsWith("is"))
+            {
+                mimeMessageGetters.put(method.getName().substring(2), method);
+            }
+        }
+    }
+
+    private Map getMap()
+    {
+        if (backingMap == null)
+        {
+            backingMap = createMap();
+        }
+
+        return backingMap;
+    }
+
+    private Map createMap()
+    {
+        Map ret = new TreeMap();
+
+        Enumeration headers;
+        try
+        {
+            headers = part.getAllHeaders();
+        }
+        catch (MessagingException e)
+        {
+            throw new RuntimeException(e);
+        }
+
+        // add all headers
+        while (headers.hasMoreElements())
+        {
+            Header header = (Header) headers.nextElement();
+            String headerName = header.getName();
+
+            Object values = ret.get(headerName);
+
+            if (values == null)
+            {
+                ret.put(headerName, header.getValue());
+            }
+            else if (values instanceof String)
+            {
+                List newValues = new ArrayList();
+                newValues.add(values);
+                newValues.add(header.getValue());
+                ret.put(headerName, newValues);
+            }
+            else if (values instanceof List)
+            {
+                ((List) values).add(header.getValue());
+            }
+        }
+
+        // add all simple get/is results (with obj. prefix)
+        Iterator iterEntries = mimeMessageGetters.entrySet().iterator();
+        while (iterEntries.hasNext())
+        {
+            Map.Entry entry = (Map.Entry) iterEntries.next();
+            String name = (String) entry.getKey();
+            Method method = (Method) entry.getValue();
+
+            try
+            {
+                Object value = method.invoke(part, null);
+                ret.put(OBJECT_PREFIX + name, value);
+            }
+            catch (IllegalAccessException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+            catch (InvocationTargetException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+        }
+
+        // add extended fields (with obj. prefix too)
+        if (part instanceof MimeMessage)
+        {
+            MimeMessage message = (MimeMessage) part;
+            try
+            {
+                Address[] address = message.getRecipients(MimeMessage.RecipientType.BCC);
+                ret.put(OBJECT_PREFIX + "Recipients.BCC", address);
+            }
+            catch (MessagingException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+            try
+            {
+                Address[] address = message.getRecipients(MimeMessage.RecipientType.CC);
+                ret.put(OBJECT_PREFIX + "Recipients.CC", address);
+            }
+            catch (MessagingException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+            try
+            {
+                Address[] address = message.getRecipients(MimeMessage.RecipientType.TO);
+                ret.put(OBJECT_PREFIX + "Recipients.TO", address);
+            }
+            catch (MessagingException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+            try
+            {
+                Address[] address = message.getRecipients(MimeMessage.RecipientType.NEWSGROUPS);
+                ret.put(OBJECT_PREFIX + "Recipients.NEWSGROUPS", address);
+            }
+            catch (MessagingException e)
+            {
+                log.debug(e.getLocalizedMessage(), e);
+            }
+        }
+
+        return ret;
+    }
+
+    public int size()
+    {
+        return getMap().size();
+    }
+
+    public boolean isEmpty()
+    {
+        return getMap().size() < 1;
+    }
+
+    public boolean containsKey(Object key)
+    {
+        return getMap().containsKey(key);
+    }
+
+    public boolean containsValue(Object value)
+    {
+        return getMap().containsValue(value);
+    }
+
+    public Object get(Object key)
+    {
+        return getMap().get(key);
+    }
+
+    public Object put(Object key, Object value)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public Object remove(Object key)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void putAll(Map t)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public void clear()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    public Set keySet()
+    {
+        return Collections.unmodifiableSet(getMap().keySet());
+    }
+
+    public Collection values()
+    {
+        return Collections.unmodifiableCollection(getMap().values());
+    }
+
+    public Set entrySet()
+    {
+        return Collections.unmodifiableSet(getMap().entrySet());
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileContentInfoFactory.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileContentInfoFactory.java
new file mode 100644
index 0000000..56cfb51
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileContentInfoFactory.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.mime;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.DefaultFileContentInfo;
+
+import javax.mail.MessagingException;
+import javax.mail.Part;
+import javax.mail.internet.ContentType;
+
+/**
+ * get access to the content info stuff for mime objects
+ *
+ * @author <a href="mailto:imario@apache.org">imario@apache.org</a>
+ * @version $Revision$ $Date$
+ */
+public class MimeFileContentInfoFactory implements FileContentInfoFactory
+{
+    public FileContentInfo create(FileContent fileContent) throws FileSystemException
+    {
+        MimeFileObject mimeFile = (MimeFileObject) fileContent.getFile();
+        Part part = mimeFile.getPart();
+
+        String contentTypeString = null;
+        String charset = null;
+
+        try
+        {
+            // special handling for multipart
+            if (mimeFile.isMultipart())
+            {
+                // get the original content type, but ...
+                contentTypeString = part.getContentType();
+
+                // .... we deliver the preamble instead of an inupt string
+                // the preamble will be delivered in UTF-8 - fixed
+                charset = MimeFileSystem.PREAMBLE_CHARSET;
+            }
+        }
+        catch (MessagingException e)
+        {
+            throw new FileSystemException(e);
+        }
+
+        if (contentTypeString == null)
+        {
+            // normal message ... get the content type
+            try
+            {
+                contentTypeString = part.getContentType();
+            }
+            catch (MessagingException e)
+            {
+                throw new FileSystemException(e);
+            }
+        }
+
+        ContentType contentType;
+        try
+        {
+            contentType = new ContentType(contentTypeString);
+        }
+        catch (MessagingException e)
+        {
+            throw new FileSystemException(e);
+        }
+
+        if (charset == null)
+        {
+            // charset might already be set by the multipart message stuff, else
+            // extract it from the contentType now
+            charset = contentType.getParameter("charset"); // NON-NLS
+        }
+
+        return new DefaultFileContentInfo(
+            contentType.getBaseType(),
+            charset);
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileObject.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileObject.java
new file mode 100644
index 0000000..574b15b
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileObject.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.mime;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.internet.MimeMultipart;
+
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.FileObjectUtils;
+
+/**
+ * A part of a MIME message.
+ *
+ * @author <a href="mailto:imario@apache.org">imario@apache.org</a>
+ * @version $Revision$ $Date$
+ */
+public class MimeFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    private Part part;
+    private Map attributeMap;
+
+    protected MimeFileObject(final FileName name,
+                            final Part part,
+                            final AbstractFileSystem fileSystem) throws FileSystemException
+    {
+        super(name, fileSystem);
+        setPart(part);
+    }
+    /**
+     * Attaches this file object to its file resource.
+     */
+    protected void doAttach() throws Exception
+    {
+        if (part == null)
+        {
+            if (!getName().equals(getFileSystem().getRootName()))
+            {
+                MimeFileObject foParent = (MimeFileObject) FileObjectUtils.getAbstractFileObject(getParent());
+                setPart(foParent.findPart(getName().getBaseName()));
+                return;
+            }
+
+            setPart(((MimeFileSystem) getFileSystem()).createCommunicationLink());
+        }
+    }
+
+    private Part findPart(String partName) throws Exception
+    {
+        if (getType() == FileType.IMAGINARY)
+        {
+            // not existent
+            return null;
+        }
+
+        if (isMultipart())
+        {
+            Multipart multipart = (Multipart)  part.getContent();
+            if (partName.startsWith(MimeFileSystem.NULL_BP_NAME))
+            {
+                int partNumber = Integer.parseInt(partName.substring(MimeFileSystem.NULL_BP_NAME.length()), 10);
+                if (partNumber < 0 || partNumber+1 > multipart.getCount())
+                {
+                    // non existent
+                    return null;
+                }
+
+                return multipart.getBodyPart(partNumber);
+            }
+
+            for (int i = 0; i<multipart.getCount(); i++)
+            {
+                Part childPart = multipart.getBodyPart(i);
+                if (partName.equals(childPart.getFileName()))
+                {
+                    return childPart;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    protected void doDetach() throws Exception
+    {
+    }
+
+    /**
+     * Determines the type of the file, returns null if the file does not
+     * exist.
+     */
+    protected FileType doGetType() throws Exception
+    {
+        if (part == null)
+        {
+            return FileType.IMAGINARY;
+        }
+
+        if (isMultipart())
+        {
+            // we cant have children ...
+            return FileType.FILE_OR_FOLDER;
+        }
+
+        return FileType.FILE;
+    }
+
+    protected String[] doListChildren() throws Exception
+    {
+        return null;
+    }
+
+    /**
+     * Lists the children of the file.  Is only called if {@link #doGetType}
+     * returns {@link org.apache.commons.vfs.FileType#FOLDER}.
+     */
+    protected FileObject[] doListChildrenResolved() throws Exception
+    {
+        if (part == null)
+        {
+            return null;
+        }
+
+        List vfs = new ArrayList();
+        if (isMultipart())
+        {
+            Object container = part.getContent();
+            if (container instanceof Multipart)
+            {
+                Multipart multipart = (Multipart) container;
+
+                for (int i = 0; i<multipart.getCount(); i++)
+                {
+                    Part part = multipart.getBodyPart(i);
+
+                    String filename = UriParser.encode(part.getFileName());
+                    if (filename == null)
+                    {
+                        filename = MimeFileSystem.NULL_BP_NAME + i;
+                    }
+
+                    MimeFileObject fo = (MimeFileObject) FileObjectUtils.getAbstractFileObject(getFileSystem().resolveFile(
+                        getFileSystem().getFileSystemManager().resolveName(
+                            getName(),
+                            filename,
+                            NameScope.CHILD)));
+                    fo.setPart(part);
+                    vfs.add(fo);
+                }
+            }
+        }
+
+        return (MimeFileObject[]) vfs.toArray(new MimeFileObject[vfs.size()]);
+    }
+
+    private void setPart(Part part)
+    {
+        this.part = part;
+        this.attributeMap = null;
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        return part.getSize();
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime()
+        throws Exception
+    {
+        Message mm = getMessage();
+        if (mm == null)
+        {
+            return -1;
+        }
+        if (mm.getSentDate() != null)
+        {
+            return mm.getSentDate().getTime();
+        }
+        if (mm.getReceivedDate() != null)
+        {
+            mm.getReceivedDate();
+        }
+        return 0;
+    }
+
+    private Message getMessage() throws FileSystemException
+    {
+        if (part instanceof Message)
+        {
+            return (Message) part;
+        }
+
+        return ((MimeFileObject) FileObjectUtils.getAbstractFileObject(getParent())).getMessage();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        if (isMultipart())
+        {
+            // deliver the preamble as the only content
+
+            String preamble = ((MimeMultipart) part.getContent()).getPreamble();
+            if (preamble == null)
+            {
+                return new ByteArrayInputStream(new byte[]{});
+            }
+            return new ByteArrayInputStream(preamble.getBytes(MimeFileSystem.PREAMBLE_CHARSET));
+        }
+
+        return part.getInputStream();
+    }
+
+    boolean isMultipart() throws MessagingException
+    {
+        return part.getContentType() != null && part.getContentType().startsWith("multipart/");
+    }
+
+    protected FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return new MimeFileContentInfoFactory();
+    }
+
+    protected Part getPart()
+    {
+        return part;
+    }
+
+    /**
+     * Returns all headers of this part.<br />
+     * The map key is a java.lang.String and the value is a:<br />
+     * <ul>
+     * <li>java.lang.Strings for single entries</li>
+     * or a
+     * <li>java.utils.List of java.lang.Strings for entries with multiple values</li>
+     * </ul>
+     */
+    protected Map doGetAttributes() throws Exception
+    {
+        if (attributeMap == null)
+        {
+            if (part != null)
+            {
+                attributeMap = new MimeAttributesMap(part);
+            }
+            else
+            {
+                attributeMap = Collections.EMPTY_MAP;
+            }
+        }
+
+        return attributeMap;
+    }
+
+    protected Enumeration getAllHeaders() throws MessagingException
+    {
+        return part.getAllHeaders();
+    }
+}
\ No newline at end of file
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileProvider.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileProvider.java
new file mode 100644
index 0000000..7e5af8c
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileProvider.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.mime;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.AbstractLayeredFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.LayeredFileName;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A provider for MIME Message.
+ *
+ * @author <a href="mailto:imario@apache.org">imario@apache.org</a>
+ * @version $Revision$ $Date$
+ */
+public class MimeFileProvider
+    extends AbstractLayeredFileProvider
+    implements FileProvider
+{
+    protected final static Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.GET_TYPE,
+        Capability.GET_LAST_MODIFIED,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.ATTRIBUTES
+    }));
+
+    public MimeFileProvider()
+    {
+        super();
+    }
+
+    /**
+     * Creates the filesystem.
+     */
+    protected FileSystem doCreateFileSystem(String scheme, final FileObject file, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        final FileName name =
+            new LayeredFileName(scheme, file.getName(), FileName.ROOT_PATH, FileType.FOLDER);
+        return new MimeFileSystem(name, file, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileSystem.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileSystem.java
new file mode 100644
index 0000000..dc17b68
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/mime/MimeFileSystem.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.mime;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+import org.apache.commons.vfs.util.SharedRandomContentInputStream;
+
+import javax.mail.MessagingException;
+import javax.mail.Part;
+import javax.mail.internet.MimeMessage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+/**
+ * An MIME file system.
+ *
+ * @author <a href="mailto:imario@apache.org">imario@apache.org</a>
+ * @version $Revision$ $Date$
+ */
+public class MimeFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    private Log log = LogFactory.getLog(MimeFileSystem.class);
+
+    public final static String NULL_BP_NAME = "_body_part_";
+    public final static String CONTENT_NAME = "_content";
+    public final static String PREAMBLE_CHARSET = "UTF-8";
+
+    private InputStream mimeStream = null;
+
+    protected MimeFileSystem(final FileName rootName, final FileObject parentLayer, final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, parentLayer, fileSystemOptions);
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name) throws FileSystemException
+    {
+        return new MimeFileObject(name, null, this);
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(MimeFileProvider.capabilities);
+    }
+
+
+    protected void doCloseCommunicationLink()
+    {
+        try
+        {
+            if (mimeStream == null)
+            {
+                return;
+            }
+
+            closeMimeStream();
+            mimeStream = null;
+        }
+        catch (IOException e)
+        {
+            log.warn(e.getLocalizedMessage(), e);
+        }
+    }
+
+    private void closeMimeStream() throws IOException
+    {
+        if (mimeStream instanceof SharedRandomContentInputStream)
+        {
+            ((SharedRandomContentInputStream) mimeStream).closeAll();
+        }
+        else
+        {
+            mimeStream.close();
+        }
+    }
+
+    public Part createCommunicationLink() throws IOException, MessagingException
+    {
+        if (mimeStream != null)
+        {
+            closeMimeStream();
+        }
+
+        FileObject parentLayer = getParentLayer();
+        if (!parentLayer.exists())
+        {
+            return null;
+        }
+
+        if (parentLayer.getFileSystem().hasCapability(Capability.RANDOM_ACCESS_READ))
+        {
+            mimeStream = new SharedRandomContentInputStream(parentLayer);
+        }
+        else
+        {
+            mimeStream = getParentLayer().getContent().getInputStream();
+        }
+        return new MimeMessage(null, mimeStream);
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileName.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileName.java
new file mode 100644
index 0000000..eba5c87
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileName.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.GenericFileName;
+
+/**
+ * An SMB URI.  Adds a share name to the generic URI.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SmbFileName
+    extends GenericFileName
+{
+    private static final int DEFAULT_PORT = 139;
+
+    private final String share;
+    private final String domain;
+    private String uriWithoutAuth;
+
+    protected SmbFileName(
+        final String scheme,
+        final String hostName,
+        final int port,
+        final String userName,
+        final String password,
+        final String domain,
+        final String share,
+        final String path,
+        final FileType type)
+    {
+        super(scheme, hostName, port, DEFAULT_PORT, userName, password, path, type);
+        this.share = share;
+        this.domain = domain;
+    }
+
+    /**
+     * Returns the share name.
+     */
+    public String getShare()
+    {
+        return share;
+    }
+
+    /**
+     * Builds the root URI for this file name.
+     */
+    protected void appendRootUri(final StringBuffer buffer, boolean addPassword)
+    {
+        super.appendRootUri(buffer, addPassword);
+        buffer.append('/');
+        buffer.append(share);
+    }
+
+    /**
+     * put domain before username if both are set
+     */
+    protected void appendCredentials(StringBuffer buffer, boolean addPassword)
+    {
+        if (getDomain() != null && getDomain().length() != 0 &&
+            getUserName() != null && getUserName().length() != 0)
+        {
+            buffer.append(getDomain());
+            buffer.append("\\");
+        }
+        super.appendCredentials(buffer, addPassword);
+    }
+
+    /**
+     * Factory method for creating name instances.
+     */
+    public FileName createName(final String path, FileType type)
+    {
+        return new SmbFileName(
+            getScheme(),
+            getHostName(),
+            getPort(),
+            getUserName(),
+            getPassword(),
+            domain,
+            share,
+            path,
+            type);
+    }
+
+    /**
+     * Construct the path suitable for SmbFile when used with NtlmPasswordAuthentication
+     */
+    public String getUriWithoutAuth() throws FileSystemException
+    {
+        if (uriWithoutAuth != null)
+        {
+            return uriWithoutAuth;
+        }
+
+        StringBuffer sb = new StringBuffer(120);
+        sb.append(getScheme());
+        sb.append("://");
+        sb.append(getHostName());
+        if (getPort() != DEFAULT_PORT)
+        {
+            sb.append(":");
+            sb.append(getPort());
+        }
+        sb.append("/");
+        sb.append(getShare());
+        sb.append(getPathDecoded());
+        uriWithoutAuth = sb.toString();
+        return uriWithoutAuth;
+    }
+
+    /**
+     * returns the domain name
+     */
+    public String getDomain()
+    {
+        return domain;
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileNameParser.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileNameParser.java
new file mode 100644
index 0000000..39cfbc1
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileNameParser.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.provider.FileNameParser;
+import org.apache.commons.vfs.provider.URLFileNameParser;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+
+/**
+ * Implementation for sftp. set default port to 139
+ */
+public class SmbFileNameParser extends URLFileNameParser
+{
+    private final static SmbFileNameParser INSTANCE = new SmbFileNameParser();
+
+    public SmbFileNameParser()
+    {
+        super(139);
+    }
+
+    public static FileNameParser getInstance()
+    {
+        return INSTANCE;
+    }
+
+    public FileName parseUri(final VfsComponentContext context, FileName base, final String filename) throws FileSystemException
+    {
+        final StringBuffer name = new StringBuffer();
+
+        // Extract the scheme and authority parts
+        final Authority auth = extractToPath(filename, name);
+
+        // extract domain
+        String username = auth.getUserName();
+        String domain = extractDomain(username);
+        if (domain != null)
+        {
+            username = username.substring(domain.length() + 1);
+        }
+
+        // Decode and adjust separators
+        UriParser.canonicalizePath(name, 0, name.length(), this);
+        UriParser.fixSeparators(name);
+
+        // Extract the share
+        final String share = UriParser.extractFirstElement(name);
+        if (share == null || share.length() == 0)
+        {
+            throw new FileSystemException("vfs.provider.smb/missing-share-name.error", filename);
+        }
+
+        // Normalise the path.  Do this after extracting the share name,
+        // to deal with things like smb://hostname/share/..
+        FileType fileType = UriParser.normalisePath(name);
+        final String path = name.toString();
+
+        return new SmbFileName(
+            auth.getScheme(),
+            auth.getHostName(),
+            auth.getPort(),
+            username,
+            auth.getPassword(),
+            domain,
+            share,
+            path,
+            fileType);
+    }
+
+    private String extractDomain(String username)
+    {
+        if (username == null)
+        {
+            return null;
+        }
+
+        for (int i = 0; i < username.length(); i++)
+        {
+            if (username.charAt(i) == '\\')
+            {
+                return username.substring(0, i);
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileObject.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileObject.java
new file mode 100644
index 0000000..bd113d1
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileObject.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import jcifs.smb.NtlmPasswordAuthentication;
+import jcifs.smb.SmbException;
+import jcifs.smb.SmbFile;
+import jcifs.smb.SmbFileInputStream;
+import jcifs.smb.SmbFileOutputStream;
+import org.apache.commons.vfs.*;
+import org.apache.commons.vfs.provider.AbstractFileObject;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.RandomAccessMode;
+import org.apache.commons.vfs.util.UserAuthenticatorUtils;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+
+/**
+ * A file in an SMB file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SmbFileObject
+    extends AbstractFileObject
+    implements FileObject
+{
+    // private final String fileName;
+    private SmbFile file;
+
+    protected SmbFileObject(final FileName name,
+                            final SmbFileSystem fileSystem) throws FileSystemException
+    {
+        super(name, fileSystem);
+        // this.fileName = UriParser.decode(name.getURI());
+    }
+
+    /**
+     * Attaches this file object to its file resource.
+     */
+    protected void doAttach() throws Exception
+    {
+        // Defer creation of the SmbFile to here
+        if (file == null)
+        {
+            file = createSmbFile(getName());
+        }
+    }
+
+    protected void doDetach() throws Exception
+    {
+        // file closed through content-streams
+        file = null;
+    }
+
+    private SmbFile createSmbFile(FileName fileName) throws MalformedURLException, SmbException, FileSystemException
+    {
+        SmbFileName smbFileName = (SmbFileName) fileName;
+
+        String path = smbFileName.getUriWithoutAuth();
+
+        UserAuthenticationData authData = null;
+        SmbFile file;
+        NtlmPasswordAuthentication auth;
+        try
+        {
+            authData = UserAuthenticatorUtils.authenticate(getFileSystem().getFileSystemOptions(), SmbFileProvider.AUTHENTICATOR_TYPES);
+
+            auth = new NtlmPasswordAuthentication(
+                UserAuthenticatorUtils.toString(
+                    UserAuthenticatorUtils.getData(
+                        authData,
+                        UserAuthenticationData.DOMAIN,
+                        UserAuthenticatorUtils.toChar(smbFileName.getDomain()))),
+                UserAuthenticatorUtils.toString(
+                    UserAuthenticatorUtils.getData(
+                        authData,
+                        UserAuthenticationData.USERNAME,
+                        UserAuthenticatorUtils.toChar(smbFileName.getUserName()))),
+                UserAuthenticatorUtils.toString(
+                    UserAuthenticatorUtils.getData(
+                        authData,
+                        UserAuthenticationData.PASSWORD,
+                        UserAuthenticatorUtils.toChar(smbFileName.getPassword()))));
+
+            file = new SmbFile(path, auth);
+        }
+        finally
+        {
+            UserAuthenticatorUtils.cleanup(authData);
+        }
+
+        if (file.isDirectory() && !file.toString().endsWith("/"))
+        {
+            file = new SmbFile(path + "/", auth);
+        }
+
+        return file;
+    }
+
+    /**
+     * Determines the type of the file, returns null if the file does not
+     * exist.
+     */
+    protected FileType doGetType() throws Exception
+    {
+        if (!file.exists())
+        {
+            return FileType.IMAGINARY;
+        }
+        else if (file.isDirectory())
+        {
+            return FileType.FOLDER;
+        }
+        else if (file.isFile())
+        {
+            return FileType.FILE;
+        }
+
+        throw new FileSystemException("vfs.provider.smb/get-type.error", getName());
+    }
+
+    /**
+     * Lists the children of the file.  Is only called if {@link #doGetType}
+     * returns {@link FileType#FOLDER}.
+     */
+    protected String[] doListChildren() throws Exception
+    {
+        // VFS-210: do not try to get listing for anything else than directories
+        if (!file.isDirectory())
+        {
+            return null;
+        }
+
+        return UriParser.encode(file.list());
+    }
+
+    /**
+     * Determines if this file is hidden.
+     */
+    protected boolean doIsHidden() throws Exception
+    {
+        return file.isHidden();
+    }
+
+    /**
+     * Deletes the file.
+     */
+    protected void doDelete() throws Exception
+    {
+        file.delete();
+    }
+
+    protected void doRename(FileObject newfile) throws Exception
+    {
+        file.renameTo(createSmbFile(newfile.getName()));
+    }
+
+    /**
+     * Creates this file as a folder.
+     */
+    protected void doCreateFolder() throws Exception
+    {
+        file.mkdir();
+        file = createSmbFile(getName());
+    }
+
+    /**
+     * Returns the size of the file content (in bytes).
+     */
+    protected long doGetContentSize() throws Exception
+    {
+        return file.length();
+    }
+
+    /**
+     * Returns the last modified time of this file.
+     */
+    protected long doGetLastModifiedTime()
+        throws Exception
+    {
+        return file.getLastModified();
+    }
+
+    /**
+     * Creates an input stream to read the file content from.
+     */
+    protected InputStream doGetInputStream() throws Exception
+    {
+        try
+        {
+            return new SmbFileInputStream(file);
+        }
+        catch (SmbException e)
+        {
+            if (e.getErrorCode() == SmbException.ERRbadfile)
+            {
+                throw new FileNotFoundException(getName());
+            }
+            else if (file.isDirectory())
+            {
+                throw new FileTypeHasNoContentException(getName());
+            }
+
+            throw e;
+        }
+    }
+
+    /**
+     * Creates an output stream to write the file content to.
+     */
+    protected OutputStream doGetOutputStream(boolean bAppend) throws Exception
+    {
+        return new SmbFileOutputStream(file, bAppend);
+    }
+
+    /**
+     * random access
+     */
+    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception
+    {
+        return new SmbFileRandomAccessContent(file, mode);
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileProvider.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileProvider.java
new file mode 100644
index 0000000..42c2581
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileProvider.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticationData;
+import org.apache.commons.vfs.provider.AbstractOriginatingFileProvider;
+import org.apache.commons.vfs.provider.FileProvider;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A provider for SMB (Samba, Windows share) file systems.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SmbFileProvider
+    extends AbstractOriginatingFileProvider
+    implements FileProvider
+{
+    protected final static Collection capabilities = Collections.unmodifiableCollection(Arrays.asList(new Capability[]
+    {
+        Capability.CREATE,
+        Capability.DELETE,
+        Capability.RENAME,
+        Capability.GET_TYPE,
+        Capability.GET_LAST_MODIFIED,
+        Capability.LIST_CHILDREN,
+        Capability.READ_CONTENT,
+        Capability.URI,
+        Capability.WRITE_CONTENT,
+        Capability.APPEND_CONTENT,
+        Capability.RANDOM_ACCESS_READ,
+        Capability.RANDOM_ACCESS_WRITE
+    }));
+
+    public final static UserAuthenticationData.Type[] AUTHENTICATOR_TYPES = new UserAuthenticationData.Type[]
+        {
+            UserAuthenticationData.USERNAME, UserAuthenticationData.PASSWORD, UserAuthenticationData.DOMAIN
+        };
+
+    public SmbFileProvider()
+    {
+        super();
+        setFileNameParser(SmbFileNameParser.getInstance());
+    }
+
+    /**
+     * Creates the filesystem.
+     */
+    protected FileSystem doCreateFileSystem(final FileName name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        return new SmbFileSystem(name, fileSystemOptions);
+    }
+
+    public Collection getCapabilities()
+    {
+        return capabilities;
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileRandomAccessContent.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileRandomAccessContent.java
new file mode 100644
index 0000000..c4b81aa
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileRandomAccessContent.java
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import jcifs.smb.SmbException;
+import jcifs.smb.SmbFile;
+import jcifs.smb.SmbRandomAccessFile;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractRandomAccessContent;
+import org.apache.commons.vfs.util.RandomAccessMode;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.UnknownHostException;
+
+/**
+ * RandomAccess for smb files
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision$ $Date$
+ */
+class SmbFileRandomAccessContent extends AbstractRandomAccessContent
+{
+    private final SmbRandomAccessFile raf;
+    private final InputStream rafis;
+
+    SmbFileRandomAccessContent(final SmbFile smbFile, final RandomAccessMode mode) throws FileSystemException
+    {
+        super(mode);
+
+        try
+        {
+            raf = new SmbRandomAccessFile(smbFile, mode.getModeString());
+            rafis = new InputStream()
+            {
+                public int read() throws IOException
+                {
+                    return raf.readByte();
+                }
+
+                public long skip(long n) throws IOException
+                {
+                    raf.seek(raf.getFilePointer() + n);
+                    return n;
+                }
+
+                public void close() throws IOException
+                {
+                    raf.close();
+                }
+
+                public int read(byte b[]) throws IOException
+                {
+                    return raf.read(b);
+                }
+
+                public int read(byte b[], int off, int len) throws IOException
+                {
+                    return raf.read(b, off, len);
+                }
+
+                public int available() throws IOException
+                {
+                    long available = raf.length() - raf.getFilePointer();
+                    if (available > Integer.MAX_VALUE)
+                    {
+                        return Integer.MAX_VALUE;
+                    }
+
+                    return (int) available;
+                }
+            };
+        }
+        catch (MalformedURLException e)
+        {
+            throw new FileSystemException("vfs.provider/random-access-open-failed.error", smbFile, e);
+        }
+        catch (SmbException e)
+        {
+            throw new FileSystemException("vfs.provider/random-access-open-failed.error", smbFile, e);
+        }
+        catch (UnknownHostException e)
+        {
+            throw new FileSystemException("vfs.provider/random-access-open-failed.error", smbFile, e);
+        }
+    }
+
+    public long getFilePointer() throws IOException
+    {
+        return raf.getFilePointer();
+    }
+
+    public void seek(long pos) throws IOException
+    {
+        raf.seek(pos);
+    }
+
+    public long length() throws IOException
+    {
+        return raf.length();
+    }
+
+    public void close() throws IOException
+    {
+        raf.close();
+    }
+
+    public byte readByte() throws IOException
+    {
+        return raf.readByte();
+    }
+
+    public char readChar() throws IOException
+    {
+        return raf.readChar();
+    }
+
+    public double readDouble() throws IOException
+    {
+        return raf.readDouble();
+    }
+
+    public float readFloat() throws IOException
+    {
+        return raf.readFloat();
+    }
+
+    public int readInt() throws IOException
+    {
+        return raf.readInt();
+    }
+
+    public int readUnsignedByte() throws IOException
+    {
+        return raf.readUnsignedByte();
+    }
+
+    public int readUnsignedShort() throws IOException
+    {
+        return raf.readUnsignedShort();
+    }
+
+    public long readLong() throws IOException
+    {
+        return raf.readLong();
+    }
+
+    public short readShort() throws IOException
+    {
+        return raf.readShort();
+    }
+
+    public boolean readBoolean() throws IOException
+    {
+        return raf.readBoolean();
+    }
+
+    public int skipBytes(int n) throws IOException
+    {
+        return raf.skipBytes(n);
+    }
+
+    public void readFully(byte b[]) throws IOException
+    {
+        raf.readFully(b);
+    }
+
+    public void readFully(byte b[], int off, int len) throws IOException
+    {
+        raf.readFully(b, off, len);
+    }
+
+    public String readUTF() throws IOException
+    {
+        return raf.readUTF();
+    }
+
+    public void writeDouble(double v) throws IOException
+    {
+        raf.writeDouble(v);
+    }
+
+    public void writeFloat(float v) throws IOException
+    {
+        raf.writeFloat(v);
+    }
+
+    public void write(int b) throws IOException
+    {
+        raf.write(b);
+    }
+
+    public void writeByte(int v) throws IOException
+    {
+        raf.writeByte(v);
+    }
+
+    public void writeChar(int v) throws IOException
+    {
+        raf.writeChar(v);
+    }
+
+    public void writeInt(int v) throws IOException
+    {
+        raf.writeInt(v);
+    }
+
+    public void writeShort(int v) throws IOException
+    {
+        raf.writeShort(v);
+    }
+
+    public void writeLong(long v) throws IOException
+    {
+        raf.writeLong(v);
+    }
+
+    public void writeBoolean(boolean v) throws IOException
+    {
+        raf.writeBoolean(v);
+    }
+
+    public void write(byte b[]) throws IOException
+    {
+        raf.write(b);
+    }
+
+    public void write(byte b[], int off, int len) throws IOException
+    {
+        raf.write(b, off, len);
+    }
+
+    public void writeBytes(String s) throws IOException
+    {
+        raf.writeBytes(s);
+    }
+
+    public void writeChars(String s) throws IOException
+    {
+        raf.writeChars(s);
+    }
+
+    public void writeUTF(String str) throws IOException
+    {
+        raf.writeUTF(str);
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return rafis;
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileSystem.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileSystem.java
new file mode 100644
index 0000000..cb22137
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/SmbFileSystem.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.util.Collection;
+
+/**
+ * An SMB file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class SmbFileSystem
+    extends AbstractFileSystem
+    implements FileSystem
+{
+    protected SmbFileSystem(final FileName rootName, final FileSystemOptions fileSystemOptions)
+    {
+        super(rootName, null, fileSystemOptions);
+    }
+
+    /**
+     * Creates a file object.
+     */
+    protected FileObject createFile(final FileName name) throws FileSystemException
+    {
+        return new SmbFileObject(name, this);
+    }
+
+    /**
+     * Returns the capabilities of this file system.
+     */
+    protected void addCapabilities(final Collection caps)
+    {
+        caps.addAll(SmbFileProvider.capabilities);
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/package.html b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/package.html
new file mode 100644
index 0000000..67a27e2
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/provider/smb/package.html
@@ -0,0 +1,19 @@
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+  
+        http://www.apache.org/licenses/LICENSE-2.0
+  
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+  -->
+<body>
+<p>The SMB/CIFS File Provider.</p>
+</body>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/FileObjectDataSource.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/FileObjectDataSource.java
new file mode 100644
index 0000000..1230c7f
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/FileObjectDataSource.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+
+import javax.activation.DataSource;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Provide access to a FileObject as DataSource
+ */
+public class FileObjectDataSource implements DataSource
+{
+    private final FileObject fo;
+
+    public FileObjectDataSource(FileObject fo)
+    {
+        this.fo = fo;
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return fo.getContent().getInputStream();
+    }
+
+    public OutputStream getOutputStream() throws IOException
+    {
+        return fo.getContent().getOutputStream();
+    }
+
+    public String getContentType()
+    {
+        try
+        {
+            return fo.getContent().getContentInfo().getContentType();
+        }
+        catch (FileSystemException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public String getName()
+    {
+        return fo.getName().getBaseName();
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/SharedRandomContentInputStream.java b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/SharedRandomContentInputStream.java
new file mode 100644
index 0000000..53ed08d
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/java/org/apache/commons/vfs/util/SharedRandomContentInputStream.java
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.util;
+
+import org.apache.commons.vfs.Capability;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.RandomAccessContent;
+
+import javax.mail.internet.SharedInputStream;
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A wrapper to an FileObject to get a {@link javax.mail.internet.SharedInputStream} 
+ *
+ * @author <a href="mailto:imario@apache.org">imario@apache.org</a>
+ * @version $Revision$ $Date$
+ */
+public class SharedRandomContentInputStream extends BufferedInputStream implements SharedInputStream
+{
+    private final Set createdStreams;
+    private final FileObject fo;
+    private final long fileStart;
+    private final long fileEnd;
+
+    private long pos;
+    private long resetCount;
+
+    private SharedRandomContentInputStream(final Set createdStreams, final FileObject fo, final long fileStart, final long fileEnd, final InputStream is) throws FileSystemException
+    {
+        super(is);
+
+        if (!fo.getFileSystem().hasCapability(Capability.RANDOM_ACCESS_READ))
+        {
+            throw new FileSystemException("vfs.util/missing-capability.error", Capability.RANDOM_ACCESS_READ);
+        }
+        
+        this.fo = fo;
+        this.fileStart = fileStart;
+        this.fileEnd = fileEnd;
+        this.createdStreams = createdStreams;
+
+        synchronized(createdStreams)
+        {
+            createdStreams.add(this);
+        }
+    }
+
+    public SharedRandomContentInputStream(final FileObject fo) throws FileSystemException
+    {
+        this(new HashSet(), fo, 0, -1, fo.getContent().getInputStream());
+    }
+
+
+    public synchronized int read() throws IOException
+    {
+        if (checkEnd())
+        {
+            return -1;
+        }
+        int r = super.read();
+        pos++;
+        resetCount++;
+        return r;
+    }
+
+    public synchronized int read(byte b[], int off, int len) throws IOException
+    {
+        if (checkEnd())
+        {
+            return -1;
+        }
+
+        if (fileEnd > -1 && calcFilePosition(len) > fileEnd)
+        {
+            // we can not read past our end
+            len = (int) (fileEnd - getFilePosition());
+        }
+
+        int nread = super.read(b, off, len);
+        pos+=nread;
+        resetCount+=nread;
+        return nread;
+    }
+
+    public synchronized long skip(long n) throws IOException
+    {
+        if (checkEnd())
+        {
+            return -1;
+        }
+
+        if (fileEnd > -1 && calcFilePosition(n) > fileEnd)
+        {
+            // we can not skip past our end
+            n = fileEnd - getFilePosition();
+        }
+
+        long nskip = super.skip(n);
+        pos+=nskip;
+        resetCount+=nskip;
+        return nskip;
+    }
+
+    /*
+    public synchronized int available() throws IOException
+    {
+        long realFileEnd = fileEnd;
+        if (realFileEnd < 0)
+        {
+            realFileEnd = fo.getContent().getSize();
+        }
+        if (realFileEnd < 0)
+        {
+            // we cant determine if there is really something available
+            return 8192;
+        }
+
+        long available = realFileEnd - (fileStart + pos);
+        if (available > Integer.MAX_VALUE)
+        {
+            return Integer.MAX_VALUE;
+        }
+
+        return (int) available;
+    }
+    */
+
+    private boolean checkEnd()
+    {
+        return fileEnd > -1 && (getFilePosition() >= fileEnd);
+    }
+
+    protected long getFilePosition()
+    {
+        return fileStart + pos;
+    }
+
+    protected long calcFilePosition(long nadd)
+    {
+        return getFilePosition()+nadd;
+    }
+
+    public synchronized void mark(int readlimit)
+    {
+        super.mark(readlimit);
+        resetCount = 0;
+    }
+
+    public synchronized void reset() throws IOException
+    {
+        super.reset();
+        pos-=resetCount;
+        resetCount=0;
+    }
+
+    public long getPosition()
+    {
+        return pos;
+    }
+
+
+    public void close() throws IOException
+    {
+        super.close();
+
+        synchronized(createdStreams)
+        {
+            createdStreams.remove(this);
+        }
+    }
+
+    public InputStream newStream(long start, long end)
+    {
+        try
+        {
+            long newFileStart = this.fileStart+start;
+            long newFileEnd = end<0?this.fileEnd:this.fileStart+end;
+
+            RandomAccessContent rac = fo.getContent().getRandomAccessContent(RandomAccessMode.READ);
+            rac.seek(newFileStart);
+            return new SharedRandomContentInputStream(
+                createdStreams,
+                fo,
+                newFileStart,
+                newFileEnd,
+                rac.getInputStream());
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void closeAll() throws IOException
+    {
+        synchronized(createdStreams)
+        {
+            SharedRandomContentInputStream[] streams = new SharedRandomContentInputStream[createdStreams.size()];
+            createdStreams.toArray(streams);
+            for (int i = 0; i<streams.length; i++)
+            {
+                streams[i].close();
+            }
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/main/resources/META-INF/vfs-providers.xml b/VFS-2.0-RC1/sandbox/src/main/resources/META-INF/vfs-providers.xml
new file mode 100644
index 0000000..773fc40
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/main/resources/META-INF/vfs-providers.xml
@@ -0,0 +1,16 @@
+<providers>
+
+	<provider class-name="org.apache.commons.vfs.provider.smb.SmbFileProvider">
+		<scheme name="smb"/>
+		<if-available class-name="jcifs.smb.SmbFile"/>
+	</provider>
+	
+	<provider class-name="org.apache.commons.vfs.provider.mime.MimeFileProvider">
+		<scheme name="mime"/>
+		<if-available class-name="javax.mail.internet.MimeMultipart"/>
+	</provider>
+
+	<extension-map extension="mime" scheme="mime"/>
+	<mime-type-map mime-type="message/rfc822" scheme="mime"/>
+
+</providers>
diff --git a/VFS-2.0-RC1/sandbox/src/site/site.xml b/VFS-2.0-RC1/sandbox/src/site/site.xml
new file mode 100644
index 0000000..61d4cb2
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/site/site.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Commons&#xA0;VFS">
+
+  <bannerRight>
+    <name>Commons&#xA0;VFS</name>
+    <src>../images/vfs-logo-white.png</src>
+    <href>../index.html</href>
+  </bannerRight>
+
+  <body>
+    <links>
+      <item name="Commons VFS Home" href="../index.html"/>
+    </links>
+
+    <menu name="Commons&#xA0;VFS">
+      <item name="Overview"                href="../index.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/FileNameTestCase.java b/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/FileNameTestCase.java
new file mode 100644
index 0000000..c4a40bc
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/FileNameTestCase.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb.test;
+
+import org.apache.commons.AbstractVfsTestCase;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.smb.SmbFileName;
+import org.apache.commons.vfs.provider.smb.SmbFileNameParser;
+
+/**
+ * Some additional SMB file name test cases.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision$ $Date$
+ */
+public class FileNameTestCase
+    extends AbstractVfsTestCase
+{
+    /**
+     * Tests parsing a URI into its parts.
+     */
+    public void testParseUri() throws Exception
+    {
+        // Simple name
+        SmbFileName name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://hostname/share/file");
+        assertEquals("smb", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(139, name.getPort());
+        assertEquals(name.getDefaultPort(), name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/file", name.getPath());
+        assertEquals("smb://hostname/share/", name.getRootURI());
+        assertEquals("smb://hostname/share/file", name.getURI());
+
+        // Name with port
+        name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://hostname:9090/share/file");
+        assertEquals("smb", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(9090, name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/file", name.getPath());
+        assertEquals("smb://hostname:9090/share/", name.getRootURI());
+        assertEquals("smb://hostname:9090/share/file", name.getURI());
+
+        // Name with no path
+        name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://hostname/share");
+        assertEquals("smb", name.getScheme());
+        assertNull(name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(139, name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/", name.getPath());
+        assertEquals("smb://hostname/share/", name.getRootURI());
+        assertEquals("smb://hostname/share/", name.getURI());
+
+        // Name with username
+        name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://user@hostname/share/file");
+        assertEquals("smb", name.getScheme());
+        assertEquals("user", name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(139, name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/file", name.getPath());
+        assertEquals("smb://user@hostname/share/", name.getRootURI());
+        assertEquals("smb://user@hostname/share/file", name.getURI());
+
+        // Name with extension
+        name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://user@hostname/share/file.txt");
+        assertEquals("smb", name.getScheme());
+        assertEquals("user", name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(139, name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/file.txt", name.getPath());
+        assertEquals("file.txt", name.getBaseName());
+        assertEquals("txt", name.getExtension());
+        assertEquals("smb://user@hostname/share/", name.getRootURI());
+        assertEquals("smb://user@hostname/share/file.txt", name.getURI());
+
+        // Name look likes extension, but isnt
+        name = (SmbFileName) SmbFileNameParser.getInstance().parseUri(null, null, "smb://user@hostname/share/.bashrc");
+        assertEquals("smb", name.getScheme());
+        assertEquals("user", name.getUserName());
+        assertNull(name.getPassword());
+        assertEquals("hostname", name.getHostName());
+        assertEquals(139, name.getPort());
+        assertEquals("share", name.getShare());
+        assertEquals("/.bashrc", name.getPath());
+        assertEquals(".bashrc", name.getBaseName());
+        assertEquals("", name.getExtension());
+        assertEquals("smb://user@hostname/share/", name.getRootURI());
+        assertEquals("smb://user@hostname/share/.bashrc", name.getURI());
+    }
+
+    /**
+     * Tests error handling in URI parser.
+     */
+    public void testBadlyFormedUri() throws Exception
+    {
+        // Does not start with smb://
+        testBadlyFormedUri("smb:", "vfs.provider/missing-double-slashes.error");
+        testBadlyFormedUri("smb:/", "vfs.provider/missing-double-slashes.error");
+        testBadlyFormedUri("smb:a", "vfs.provider/missing-double-slashes.error");
+
+        // Missing hostname
+        testBadlyFormedUri("smb://", "vfs.provider/missing-hostname.error");
+        testBadlyFormedUri("smb://:21/share", "vfs.provider/missing-hostname.error");
+        testBadlyFormedUri("smb:///share", "vfs.provider/missing-hostname.error");
+
+        // Empty port
+        testBadlyFormedUri("smb://host:", "vfs.provider/missing-port.error");
+        testBadlyFormedUri("smb://host:/share", "vfs.provider/missing-port.error");
+        testBadlyFormedUri("smb://host:port/share/file", "vfs.provider/missing-port.error");
+
+        // Missing absolute path
+        testBadlyFormedUri("smb://host:90a", "vfs.provider/missing-hostname-path-sep.error");
+        testBadlyFormedUri("smb://host?a", "vfs.provider/missing-hostname-path-sep.error");
+
+        // Missing share name
+        testBadlyFormedUri("smb://host", "vfs.provider.smb/missing-share-name.error");
+        testBadlyFormedUri("smb://host/", "vfs.provider.smb/missing-share-name.error");
+        testBadlyFormedUri("smb://host:9090/", "vfs.provider.smb/missing-share-name.error");
+    }
+
+    /**
+     * Tests that parsing a URI fails with the expected error.
+     */
+    private void testBadlyFormedUri(final String uri, final String errorMsg)
+    {
+        try
+        {
+            SmbFileNameParser.getInstance().parseUri(null, null, uri);
+            fail();
+        }
+        catch (final FileSystemException e)
+        {
+            assertSameMessage(errorMsg, uri, e);
+        }
+    }
+}
diff --git a/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/SmbProviderTestCase.java b/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/SmbProviderTestCase.java
new file mode 100644
index 0000000..24e234d
--- /dev/null
+++ b/VFS-2.0-RC1/sandbox/src/test/java/org/apache/commons/vfs/provider/smb/test/SmbProviderTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.vfs.provider.smb.test;
+
+import junit.framework.Test;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.smb.SmbFileProvider;
+import org.apache.commons.vfs.test.AbstractProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestConfig;
+import org.apache.commons.vfs.test.ProviderTestSuite;
+
+/**
+ * Tests for the SMB file system.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ */
+public class SmbProviderTestCase
+    extends AbstractProviderTestConfig
+    implements ProviderTestConfig
+{
+    private static final String TEST_URI = "test.smb.uri";
+    public static Test suite() throws Exception
+    {
+        if (System.getProperty(TEST_URI) != null)
+        {
+            return new ProviderTestSuite(new SmbProviderTestCase());
+        }
+        else
+        {
+            return notConfigured(SmbProviderTestCase.class);
+        }
+    }
+
+    /**
+     * Prepares the file system manager.
+     */
+    public void prepare(final DefaultFileSystemManager manager)
+        throws Exception
+    {
+        manager.addProvider("smb", new SmbFileProvider());
+    }
+
+    /**
+     * Returns the base folder for tests.
+     */
+    public FileObject getBaseTestFolder(final FileSystemManager manager) throws Exception
+    {
+        final String uri = System.getProperty(TEST_URI);
+        return manager.resolveFile(uri);
+    }
+}
diff --git a/VFS-2.0-RC1/src/assembly/bin.xml b/VFS-2.0-RC1/src/assembly/bin.xml
new file mode 100644
index 0000000..5762291
--- /dev/null
+++ b/VFS-2.0-RC1/src/assembly/bin.xml
@@ -0,0 +1,44 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+    <id>bin</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <includeSiteDirectory>false</includeSiteDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>LICENSE.txt</include>
+                <include>NOTICE.txt</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target</directory>
+            <outputDirectory></outputDirectory>
+            <includes>
+                <include>*.jar</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>target/site/apidocs</directory>
+            <outputDirectory>apidocs</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/VFS-2.0-RC1/src/assembly/src.xml b/VFS-2.0-RC1/src/assembly/src.xml
new file mode 100644
index 0000000..5a8d1fb
--- /dev/null
+++ b/VFS-2.0-RC1/src/assembly/src.xml
@@ -0,0 +1,40 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+    <id>src</id>
+    <formats>
+        <format>tar.gz</format>
+        <format>zip</format>
+    </formats>
+    <baseDirectory>${project.artifactId}-${project.version}-src</baseDirectory>
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>checkstyle.xml</include>
+                <include>findbugs-exclude-filter.xml</include>
+                <include>LICENSE.txt</include>
+                <include>NOTICE.txt</include>
+                <include>pom.xml</include>
+                <include>PROPOSAL.html</include>
+                <include>RELEASE-NOTES.txt</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>src</directory>
+        </fileSet>
+    </fileSets>
+</assembly>
diff --git a/VFS-2.0-RC1/src/changes/changes.xml b/VFS-2.0-RC1/src/changes/changes.xml
new file mode 100644
index 0000000..0c4f6c5
--- /dev/null
+++ b/VFS-2.0-RC1/src/changes/changes.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<document>
+  <properties>
+    <title>Changes</title>
+    <author email="rgoers@apache.org">Ralph Goers</author>
+  </properties>
+
+  <body>
+    <release version="2.0" date="in SVN" description="">
+      <action dev="rgoers" type="fix" issue="VFS-305" due-to="Tom">
+        Add encoding option to FTP provider.
+      </action>
+       <action dev="rgoers" type="fix" issue="VFS-315" due-to="David Hausladen">
+        Fix potential NullPointerException if the DavProperty is null or contains null values.
+      </action>
+       <action dev="rgoers" type="fix" issue="VFS-316" due-to="David Hausladen">
+        Add option for preemptive authentication for HTTP based protocols.
+      </action>
+       <action dev="rgoers" type="fix" issue="VFS-322" due-to="Curtis Boyden">
+        Allow tar files that contain files over 2GB in size.
+      </action>
+       <action dev="rgoers" type="fix" issue="VFS-324" due-to="sebb">
+        Clear the cache in RamFileSystem and the children in RamFileData.
+      </action>
+      <action dev="sebb" type="fix" issue="VFS-319" due-to="sebb">
+        Typo in FtpsFileSystemConfigBuilder.setFtpsType
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-227" due-to="Sergey Vladimirov">
+        InputStream and RandomAccessContent memory leak in FileContentThreadData
+      </action>
+      <action dev="rgoers" type="update" issue="VFS-263" due-to="Ingo Maas">
+        WebdavFileObject does not implement doSetAttribute()
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-259" due-to="Marek Zawirski">
+        Http and Webdav FIleContentInfoFactory: undress to AbstractFileObject before casting
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-261" due-to="Simon Olofsson">
+        WebDAV upload corrupts binary files
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-276" due-to="Vince Bonfanti">
+        add ProviderTestConfig.getDefaultFileSystemManager() method
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-282" due-to="Alexey">
+        SftpFileProvider and SftpFileSystemConfigBuilder can't change ssh authentication methods
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-269" due-to="Marek Zawirski">
+        HttpFileObject: unsupported content over 2GB length
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-287" due-to="Mircea-Eugen Ionica">
+        LocalFileName objects are not released from AbstractFileSystem.listenerMap when all listeners are removed.
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-216" due-to="Reetu Mutti">
+        The FTP Configuration includes an option to set a timeout for the data connection, but not for the socket
+        timeout. This is a problem, as idle sockets can cause your download to hang forever and never timeout.
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-289" due-to="Kirill Safonov">
+        FTP connection is not released If exception is thrown out of FtpFileObject.doGetOutputStream().
+      </action>
+      <action dev="rgoers" type="fix" issue="VFS-286" due-to="Kirill Safonov">
+        SftpFileObject.doListChildrenResolved() changes the working dir before doing ChannelSftp.ls() call.
+        If ls() throws an exception, the current directory is not reset. All the subsequent operations that rely on the
+        current dir will fail trying to change into nonexistent directory.
+      </action>
+      <action dev="rgoers" type="add" issue="VFS-244">
+        Rename HttpRandomAccesContent to HttpRandomAccessContent.
+      </action>
+    </release>
+  </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.png b/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.png
new file mode 100644
index 0000000..2477eb0
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.png
Binary files differ
diff --git a/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.xcf b/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.xcf
new file mode 100644
index 0000000..cc392fc
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/resources/images/vfs-logo-white.xcf
Binary files differ
diff --git a/VFS-2.0-RC1/src/site/site.xml b/VFS-2.0-RC1/src/site/site.xml
new file mode 100644
index 0000000..6dc1313
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/site.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project name="Commons&#xA0;VFS">
+
+  <bannerRight>
+    <name>Commons&#xA0;VFS</name>
+    <src>/images/vfs-logo-white.png</src>
+    <href>/index.html</href>
+  </bannerRight>
+
+  <body>
+
+    <menu name="Commons&#xA0;VFS">
+      <item name="Overview"                href="/index.html"/>
+      <item name="Download and Build"      href="/download.html"/>
+      <item name="3rd party plugins"       href="/3rdparty.html"/>
+      <item name="Using the API"           href="/api.html"/>
+      <item name="API JavaDocs"            href="/apidocs/index.html"/>
+      <item name="File Systems"            href="/filesystems.html"/>
+      <item name="Ant Tasks"               href="/anttasks.html"/>
+      <item name="Wiki"                    href="http://wiki.apache.org/commons/VFS"/>
+    </menu>
+
+    <menu name="Development">
+      <item name="Testing"                 href="/testing.html"/>
+      <item name="Mailing Lists"           href="/mail-lists.html"/>
+      <item name="Issue Tracking"          href="/issue-tracking.html"/>
+      <item name="Source Repository"       href="/source-repository.html"/>
+      <item name="To Do List"              href="/todo.html"/>
+    </menu>
+      
+    <menu name="Components">
+      <item name="Core" href="commons-vfs/index.html"/>
+      <item name="Examples" href="commons-vfs-examples/index.html"/>
+      <item name="Sandbox" href="commons-vfs-sandbox/index.html"/>
+    </menu>
+  </body>
+
+</project>
diff --git a/VFS-2.0-RC1/src/site/xdoc/3rdparty.xml b/VFS-2.0-RC1/src/site/xdoc/3rdparty.xml
new file mode 100644
index 0000000..3383516
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/3rdparty.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<document>
+    <properties>
+        <title>3rd party plugins</title>
+        <author email="imario@apache.org">Mario Ivankovits</author>
+    </properties>
+
+    <body>
+        <section name="External plugins">
+
+            <p>
+                Commons VFS provides a way to extend it by simply placing plugin-jars
+                into the classpath.
+            </p>
+
+            <p>Some external plugins:</p>
+            <ul>
+                <li>ISO 9660 - <a href="http://loopy.sourceforge.net">http://loopy.sourceforge.net</a><br/>
+                    Reads .iso files
+                </li>
+            </ul>
+
+        </section>
+
+    </body>
+</document>
+
diff --git a/VFS-2.0-RC1/src/site/xdoc/anttasks.xml b/VFS-2.0-RC1/src/site/xdoc/anttasks.xml
new file mode 100644
index 0000000..50c0852
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/anttasks.xml
@@ -0,0 +1,292 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+    <properties>
+        <title>Ant Tasks</title>
+        <author email="adammurdoch@apache.org">Adam Murdoch</author>
+    </properties>
+
+    <body>
+        <section name="Ant Tasks">
+            <p>
+                Commons VFS includes several Ant tasks that can be used
+                to create, delete, copy and move files of any supported type.
+                The tasks are:
+            </p>
+            <ul>
+                <li>
+                    <a href="#V-Copy">
+                        <code>&lt;v-copy&gt;</code>
+                    </a>
+                    .
+                    Copies a set of source folders and files to a destination
+                    folder.
+                </li>
+                <li>
+                    <a href="#V-Delete">
+                        <code>&lt;v-delete&gt;</code>
+                    </a>
+                    .
+                    Deletes a file or folder.
+                </li>
+                <li>
+                    <a href="#V-Mkdir">
+                        <code>&lt;v-mkdir&gt;</code>
+                    </a>
+                    .
+                    Creates a folder.
+                </li>
+                <li>
+                    <a href="#V-Move">
+                        <code>&lt;v-move&gt;</code>
+                    </a>
+                    .
+                    Moves a set of source folders and files to a destination
+                    folder.
+                </li>
+                <li>
+                    <a href="#V-Sync">
+                        <code>&lt;v-sync&gt;</code>
+                    </a>
+                    .
+                    Synchronises a destination folder with a set of source
+                    folder and files.
+                </li>
+            </ul>
+            <p>
+                All file name attributes support relative and absolute local
+                file names, and
+                <a href="filesystems.html">absolute URI</a>
+                .
+                File names are interpreted relative to the Ant project's base
+                directory.
+            </p>
+
+            <subsection name="Using the Tasks">
+                <p>
+                    To use the Ant tasks, copy commons-vfs.jar and its
+                    dependencies into the
+                    <code>$ANT_HOME/lib</code>
+                    directory,
+                    and use the following in your Ant scipt to define the tasks:
+                </p>
+
+                <source><![CDATA[
+<taskdef resource="org/apache/commons/vfs/tasks/tasks.properties"/>
+                    ]]></source>
+
+                <p>
+                    Alternatively, you can provide an explicit classpath when
+                    you define the tasks:
+                </p>
+
+                <source><![CDATA[
+<taskdef resource="org/apache/commons/vfs/tasks/tasks.properties">
+    <classpath> ... </classpath>
+</taskdef>
+                    ]]></source>
+
+                <p>
+                    You can also use antlib:
+                    <br/>
+                    <b>Notice: VFS tasks registered that way do not have te "v-" prefix.</b>
+                    If you migrate to antlib simply replace "v-" by e.g. "vfs:" or whatever
+                    namespace you use.
+                </p>
+
+                <source><![CDATA[
+<project ... xmlns:vfs="antlib:org.apache.commons.vfs.tasks">
+    <target name="dosomething">
+        <vfs:copy .../>
+    </target>
+</project>
+                    ]]></source>
+
+            </subsection>
+        </section>
+
+        <section name="V-Copy">
+            <p>Copies a set of files to a destination folder. Does not copy
+                source files where the destination file exists and is newer than
+                the source file. The copy task takes the following attributes:</p>
+
+            <table>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                    <th>Required</th>
+                </tr>
+                <tr>
+                    <td>destdir</td>
+                    <td>The destination folder. This folder is created if it
+                        does not exist.</td>
+                    <td rowspan="2">One only</td>
+                </tr>
+                <tr>
+                    <td>destfile</td>
+                    <td>The destination file. Can only be used if there is a
+                        single source file.</td>
+                </tr>
+                <tr>
+                    <td>srcdir</td>
+                    <td>The source folder. If used the includes and desdir
+                        attributes should be specified.</td>
+                    <td>No</td>
+                </tr>
+                <tr>
+                    <td>includes</td>
+                    <td>A comma or space separated list of files. The files
+                        are resolved in combination with the specified
+                        srcdir attribute.</td>
+                    <td>Only if srcdir is specified.</td>
+                </tr>
+                <tr>
+                    <td>overwrite</td>
+                    <td>Always copy files, ignoring the last-modified time of
+                        the destination file.</td>
+                    <td>No, default is
+                        <code>false</code>
+                        .
+                    </td>
+                </tr>
+                <tr>
+                    <td>preservelastmodified</td>
+                    <td>Set the last-modified time of destination files to
+                        the same value as the source files. May not be supported
+                        by the destination file system.</td>
+                    <td>No, default is
+                        <code>true</code>
+                        .
+                    </td>
+                </tr>
+                <tr>
+                    <td>srcdirisbase</td>
+                    <td>Set whether the source directory should be used as base directory.
+                        If set to true, the subdirectories of the specified directories will be copied as well.</td>
+                    <td>No, default is
+                        <code>false</code>
+                        .
+                    </td>
+                </tr>
+                <tr>
+                    <td>src</td>
+                    <td>A source file or folder to copy. Copies all descendents
+                        of a folder.</td>
+                    <td>No</td>
+                </tr>
+            </table>
+
+            <subsection name="Nested Elements">
+                <p>
+                    <b>
+                        <code>&lt;src&gt;</code>
+                    </b>
+                </p>
+
+                <p>Defines a source file or folder to copy. It takes the
+                    following attributes:</p>
+
+                <table>
+                    <tr>
+                        <th>Name</th>
+                        <th>Description</th>
+                        <th>Required</th>
+                    </tr>
+                    <tr>
+                        <td>file</td>
+                        <td>The source file.</td>
+                        <td>Yes</td>
+                    </tr>
+                </table>
+            </subsection>
+
+        </section>
+
+        <section name="V-Move">
+            <p>Moves a set of files to a destination folder. Has the same
+                attributes and elements as the copy task and following attributes:</p>
+            <table>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                    <th>Required</th>
+                </tr>
+                <tr>
+                    <td>tryRename</td>
+                    <td>The destination folder. This folder is created if it
+                        does not exist.</td>
+                    <td>No, default is
+                        <code>false</code>
+                    </td>
+                </tr>
+            </table>
+        </section>
+
+        <section name="V-Sync">
+            <p>Synchronises a destination folder with a set of source files.
+                Has the same attributes and elements as the copy task.</p>
+        </section>
+
+        <section name="V-Delete">
+            <p>Deletes a file or folder. It takes the following attributes:</p>
+
+            <table>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                    <th>Required</th>
+                </tr>
+                <tr>
+                    <td>file</td>
+                    <td>The file or folder to delete. All descendents of
+                        the folder are deleted.</td>
+                    <td rowspan="2">One only</td>
+                </tr>
+                <tr>
+                    <td>srcdir</td>
+                    <td>The source folder. If used the includes attribute
+                        should be specified.</td>
+                </tr>
+                <tr>
+                    <td>includes</td>
+                    <td>A comma or space separated list of files. The files
+                        are resolved in combination with the specified
+                        srcdir attribute.</td>
+                    <td>Only if srcdir is specified.</td>
+                </tr>
+            </table>
+        </section>
+
+        <section name="V-Mkdir">
+            <p>Creates a folder. It takes the following attributes:</p>
+
+            <table>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                    <th>Required</th>
+                </tr>
+                <tr>
+                    <td>dir</td>
+                    <td>The folder create.</td>
+                    <td>Yes</td>
+                </tr>
+            </table>
+
+        </section>
+    </body>
+</document>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/src/site/xdoc/api.xml b/VFS-2.0-RC1/src/site/xdoc/api.xml
new file mode 100644
index 0000000..28964ea
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/api.xml
@@ -0,0 +1,379 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+    <properties>
+        <title>Using The API</title>
+        <author email="adammurdoch@apache.org">Adam Murdoch</author>
+    </properties>
+
+    <body>
+        <section name="Using The API">
+            <p>
+                The
+                <a href="apidocs/org/apache/commons/vfs/FileSystemManager.html">FileSystemManager</a>
+                interface provides access to Commons VFS.  Using this interface
+                you can locate files and create file systems.
+                There are a
+                <a href="#Configuring Commons VFS">number of ways</a>
+                to obtain a
+                <code>FileSystemManager</code> instance.
+                The simplest is to use the static
+                <a href="apidocs/org/apache/commons/vfs/VFS.html#getManager()">VFS.getManager()</a>
+                method, which returns the default Commons VFS implementation.
+            </p>
+
+            <p>
+                Once you have a
+                <code>FileSystemManager</code>, you can use its
+                <code>resolveFile()</code> methods to locate a file by name.
+                For example:
+            </p>
+
+            <source><![CDATA[
+FileSystemManager fsManager = VFS.getManager();
+FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );
+                ]]></source>
+
+            <p>
+                Each file is represented by a
+                <a href="apidocs/org/apache/commons/vfs/FileObject.html">FileObject</a>
+                instance.  Using this interface you can create or delete the
+                file, list its children, read or write its content, and so on.
+                For example:
+            </p>
+
+            <source><![CDATA[
+// Locate the Jar file
+FileSystemManager fsManager = VFS.getManager();
+FileObject jarFile = fsManager.resolveFile( "jar:lib/aJarFile.jar" );
+
+// List the children of the Jar file
+FileObject[] children = jarFile.getChildren();
+System.out.println( "Children of " + jarFile.getName().getURI() );
+for ( int i = 0; i < children.length; i++ )
+{
+    System.out.println( children[ i ].getName().getBaseName() );
+}
+                ]]></source>
+
+            <p>
+                In some cases you might want to explicitely free resources allocated by the filesystem.
+                You can do this by calling
+                <a href="apidocs/org/apache/commons/vfs/FileSystemManager.html#closeFileSystem">VFS.getManager().closeFileSystem(fs)</a>.
+                If you use VFS as singleton (as described above) you should take care that this will close the filesystem for
+                all threads.<br />
+                In other words, do not close any globally used filesystem like the one for local files.  
+            </p>
+
+            <p>
+                See the
+                <a href="apidocs/org/apache/commons/vfs/FileObject.html">FileObject</a>
+                Javadocs for more detail.
+            </p>
+
+            <subsection name="Cache">
+                <p>
+                    Commons VFS uses a <a href="apidocs/org/apache/commons/vfs/cache/SoftRefFilesCache.html">SoftRefFilesCache</a> to release memory if a file is no longer used by the application.
+                </p>
+                <p>
+                    This cache will return the same instance for a file as long as it is "strongly reachable" e.g. you
+                    hold a reference to this object. If the FileObject is no longer reachable, and the jvm needs some memory,
+                    it will be released.
+                </p>
+                <p>
+                    There is also a internal cache of each file object avoid the need to access the network layer. Now its possible
+                    to configure this behviour through the use of <a href="apidocs/org/apache/commons/vfs/CacheStrategy.html">CacheStrategy</a>.
+                    <br />
+                    Do this on the DefaultFileSystemManager. For example:
+                    <code>
+                        ((DefaultFileSystemManager) VFS.getManager()).setCacheStrategy(CacheStrategy.ON_CALL)
+                    </code>
+                </p>
+            </subsection>
+
+            <subsection name="User Authentication">
+                <p>
+                    You can put the credentials into the url, but the drawback here is, that it is
+                    easily possible to get access to the password.
+                </p>
+                <p>
+                    To solve you can use the
+                    <a href="apidocs/org/apache/commons/vfs/UserAuthenticator.html">UserAuthenticator</a>
+                </p>
+                <p>
+                    For example:
+                    <code>
+                        StaticUserAuthenticator auth = new StaticUserAuthenticator("username", "password", null);
+                        FileSystemOptions opts = new FileSystemOptions();
+                        DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, auth);
+
+                        FileObject fo = VFS.getManager().resolveFile("smb://host/anyshare/dir", opts);
+                    </code>
+                </p>
+                <p>
+                    Internally the UserAuthenticator uses char arrays which will be zeroed before it is
+                    freed for garbage collection.Unhappily none of the current libraries use char
+                    arrays and so VFS has to create a string. Thus, the main advantage
+                    of this solution - security - is lost, but hey, thats not VFS fault ;-)
+                </p>
+                <p>
+                    VFS calls <code>UserAuthenticator.requestAuthentication</code> each time it
+                    requires credentials, it depends on the filesystem implementation how often
+                    this might be. For example, with FTP this is on every connection, in SMB/JCIFS
+                    this is for EVERY OBJECT. It is up to you how long you will cache credentials
+                    of if you would like to provide a "save credentials" checkbox.
+                </p>
+            </subsection>
+
+            <subsection name="Examples">
+                <p>
+                    For an example of using the API, take a look at the classes
+                    in the
+                    <a href="apidocs/org/apache/commons/vfs/example/package-summary.html">example</a>
+                    package.
+                </p>
+            </subsection>
+
+        </section>
+
+        <section name="Configuring Commons VFS">
+            <p>
+                Commons VFS is represented using the
+                <a href="apidocs/org/apache/commons/vfs/FileSystemManager.html">FileSystemManager</a>
+                interface.  There are a number of ways to create and configure a
+                <code>FileSystemManager</code> instance.
+            </p>
+            <p>
+                The simplest method is to use the static
+                <a href="apidocs/org/apache/commons/vfs/VFS.html#getManager()">VFS.getManager()</a>
+                method, which returns the default Commons VFS implementation.
+            </p>
+            <p>
+                This method will also automatically scan the classpath for a /META-INF/vfs-providers.xml file
+                (also in jar files).
+                If such a file is found Commons VFS uses it in <u>addition</u> to the default providers.xml.
+                This allows you to start using a new filesystem by simply drop its implementation into the classpath.
+                The configuration file format is described below.<br />
+                <b>Notice:</b> Currently it is not allowed to override a already configured filesystem. Commons VFS throws
+                an exception if there is already a filesystem for a scheme.
+            </p>
+
+            <p>
+                To configure Commons VFS programatically, you can create an
+                instance of
+                <a href="apidocs/org/apache/commons/vfs/impl/DefaultFileSystemManager.html">DefaultFileSystemManager</a>
+                and configure it manually.  The default constructor
+                <code>DefaultFileSystemManager</code> creates a manager that
+                is completely empty.  You will have to add file providers to it
+                to make it do anything useful.
+            </p>
+            <p>
+                Here are the steps for using
+                <code>DefaultFileSystemManager</code>:
+            </p>
+            <ol>
+                <li>Create a new instance.</li>
+                <li>
+                    Set the logger for the manager and all its components,
+                    using
+                    <code>setLogger()</code>.  This step is
+                    optional, and if skipped, the manager will use the default
+                    logger provided by Commons Logging.
+                </li>
+                <li>
+                    Add file providers, using
+                    <code>addProvider()</code>.
+                </li>
+                <li>
+                    Set the default provider, using
+                    <code>setDefaultProvider()</code>.  This step is optional.
+                    See
+                    <a href="apidocs/org/apache/commons/vfs/provider/url/UrlFileProvider.html">UrlFileProvider</a>
+                    for a useful default provider.
+                </li>
+                <li>
+                    Set the file replicator, using
+                    <code>setReplicator()</code>.
+                    This step is optional.
+                </li>
+                <li>
+                    Set the temporary file store, using
+                    <code>setTemporaryFileStore()</code>.
+                    This step is optional.
+                </li>
+                <li>
+                    Set the base file using
+                    <code>setBaseFile()</code>.  The
+                    base file is used to resolve relative URI passed to
+                    <code>resolveFile()</code>.  This step is optional.
+                </li>
+                <li>
+                    Initialise the manager using
+                    <code>init()</code>.
+                </li>
+            </ol>
+            <p>
+                You should make sure that you call
+                <code>close()</code> on the
+                manager when you are finished with it.
+            </p>
+
+            <p>
+                The third method for configuring Commons VFS, is to configure
+                it from a file.  Create an instance of
+                <a href="apidocs/org/apache/commons/vfs/impl/StandardFileSystemManager.html">StandardFileSystemManager</a>,
+                and use its
+                <code>setConfiguration()</code> method to set the
+                location of the configuration file to use.  The configuration
+                file format is described below.
+            </p>
+
+            <p>
+                <code>StandardFileSystemManager</code> is a subclass of
+                <code>DefaultFileSystemManager</code>, so you can also
+                configure it programmatically, as described above.
+            </p>
+            <subsection name="Configuration File">
+                <p>
+                    The configuration file is an XML file.  The root element
+                    of the configuration file should be a
+                    <code>&lt;providers&gt;</code> element.
+                    The
+                    <code>&lt;providers&gt;</code> element may contain:
+                </p>
+                <ul>
+                    <li>Zero or more
+                        <code>&lt;provider&gt;</code> elements.
+                    </li>
+                    <li>An optional
+                        <code>&lt;default-provider&gt;</code> element.
+                    </li>
+                    <li>Zero or more
+                        <code>&lt;extension-map&gt;</code> elements.
+                    </li>
+                    <li>Zero or more
+                        <code>&lt;mime-type-map&gt;</code> elements.
+                    </li>
+                </ul>
+
+                <p>
+                    <b>
+                        <code>&lt;provider&gt;</code>
+                    </b>
+                </p>
+                <p>
+                    The
+                    <code>&lt;provider&gt;</code> element defines a file
+                    provider.   It must have a
+                    <code>class-name</code> attribute,
+                    which specifies the fully-qualified name of the provider
+                    class.  The provider class must be public, and must have a
+                    public constructor with an FileSystemManager argument which
+                    allows the systems to pass the used filesystem manager.
+                </p>
+                <p>
+                    The
+                    <code>&lt;provider&gt;</code> element may contain
+                    zero or more
+                    <code>&lt;scheme&gt;</code> elements,
+                    and zero or more
+                    <code>&lt;if-available&gt;</code> elements.
+                </p>
+                <p>
+                    The
+                    <code>&lt;scheme&gt;</code> element defines a URI scheme
+                    that the provider will handle.  It must have a
+                    <code>name</code> attribute, which specifies the URI scheme.
+                </p>
+                <p>
+                    The
+                    <code>&lt;if-available&gt;</code> elements is used to
+                    disable the provider if certain classes are not present in
+                    the class-path.
+                    It must have a
+                    <code>class-name</code> attribute, which
+                    specifies the fully qualified name of a class to test for.
+                    If the class cannot be found, the provider is not registered.
+                </p>
+
+                <p>
+                    <b>
+                        <code>&lt;default-provider&gt;</code>
+                    </b>
+                </p>
+                <p>
+                    The
+                    <code>&lt;default-provider&gt;</code> element defines
+                    the default provider.  It has the same format as the
+                    <code>&lt;provider&gt;</code> element.
+                </p>
+
+                <p>
+                    <b>
+                        <code>&lt;extension-map&gt;</code>
+                    </b>
+                </p>
+                <p>
+                    The
+                    <code>&lt;extension-map&gt;</code> element defines
+                    a mapping from a file's extension to the provider that
+                    should handle files with that extension.
+                    It must have an
+                    <code>extension</code> attribute, which
+                    specifies the extension, and a
+                    <code>scheme</code> attribute,
+                    which specifies the URI scheme of the provider.
+                </p>
+
+                <p>
+                    <b>
+                        <code>&lt;mime-type-map&gt;</code>
+                    </b>
+                </p>
+                <p>
+                    The
+                    <code>&lt;mime-type-map&gt;</code> element defines
+                    a mapping from a file's MIME type to the provider that
+                    should handle files with that MIME type.
+                    It must have an
+                    <code>mime-type</code> attribute, which
+                    specifies the MIME type, and a
+                    <code>scheme</code> attribute,
+                    which specified the URI scheme of the provider.
+                </p>
+
+                <p>
+                    Below is an example configuration file:
+                </p>
+                <source><![CDATA[
+<providers>
+    <provider class-name="org.apache.commons.vfs.provider.zip.ZipFileProvider">
+        <scheme name="zip"/>
+    </provider>
+    <extension-map extension="zip" scheme="zip"/>
+    <mime-type-map mime-type="application/zip" scheme="zip"/>
+    <provider class-name="org.apache.commons.vfs.provider.ftp.FtpFileProvider">
+        <scheme name="ftp"/>
+        <if-available class-name="org.apache.commons.net.ftp.FTPFile"/>
+    </provider>
+    <default-provider class-name="org.apache.commons.vfs.provider.url.UrlFileProvider"/>
+</providers>
+                    ]]></source>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/src/site/xdoc/download.xml b/VFS-2.0-RC1/src/site/xdoc/download.xml
new file mode 100644
index 0000000..0b81306
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/download.xml
@@ -0,0 +1,139 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+
+    <properties>
+        <title>Download</title>
+        <author email="adammurdoch@apache.org">Adam Murdoch</author>
+    </properties>
+
+    <body>
+        <section name="Download">
+            <p>
+                The latest release of Commons VFS can be found
+                <a href="http://commons.apache.org/downloads/download_vfs.cgi">here</a>
+                .
+            </p>
+            <p>
+                You will also need to download the jars used by Commons VFS.
+                These are listed below:
+            </p>
+            <table>
+                <tr>
+                    <th>Dependency</th>
+                    <th>Required For</th>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://commons.apache.org/logging/">Commons Logging</a>
+                        Version 1.1.1 or later.
+                    </td>
+                    <td>All</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://commons.apache.org/collections/">Commons Collections</a>
+                        Version 3.1
+                    </td>
+                    <td>LRU Cache (optional)</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://commons.apache.org/net/">Commons Net</a>
+                        Version 1.4.1 or later.
+                    </td>
+                    <td rowspan="2">FTP</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://commons.apache.org/httpclient/">Commons Httpclient</a>
+                        .
+                        Version 2.0.
+                    </td>
+                    <td>
+                        WebDAV
+                        <br/>
+                        HTTP, URI Utils
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://jackrabbit.apache.org">Apache Jackrabbit</a>
+                        Version 1.5.2 or later
+                    </td>
+                    <td>WebDAV</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://jcifs.samba.org/">jCIFS</a>
+                        Version 0.8.3 or later.
+                    </td>
+                    <td>CIFS (VFS sandbox)</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://www.jcraft.com/jsch/">JSch</a>
+                        Version 0.1.42 or later.
+                    </td>
+                    <td>SFTP</td>
+                </tr>
+                <tr>
+                    <td>
+                        <a href="http://java.sun.com/products/javamail/">javamail</a>
+                        Version 1.4
+                    </td>
+                    <td>mime (VFS sandbox)</td>
+                </tr>
+            </table>
+        </section>
+        <section name="Building Commons VFS">
+            <p>
+                To obtain the Commons VFS source, you can either:
+            </p>
+            <ul>
+                <li>
+                    Check the source out of SVN using:
+                    <br/>
+                    HEAD:
+                    <code>svn co http://svn.apache.org/repos/asf/commons/proper/vfs/trunk vfs</code>
+                    <br/>
+                    For a certain version please look at
+                    <a href="http://svn.apache.org/repos/asf/commons/proper/vfs/tags">
+                        http://svn.apache.org/repos/asf/commons/proper/vfs/tags</a>
+                </li>
+                <li>
+                    Download a nightly source snapshot from
+                    <a href="http://people.apache.org/builds/commons/nightly/commons-vfs/">here</a>
+                    .
+                </li>
+            </ul>
+            <p>
+                To build Commons VFS, you can either:
+            </p>
+            <ul>
+                <li>
+                    Use
+                    <a href="http://maven.apache.org">Maven</a>
+                    2.1.0 or later. Use mvn install to build all the core, examples and sandbox. The
+                    jars will then be installed for use by other maven-based builds. The jars can either
+                    be copied from the local maven repository or the target sub-directories for non-Maven
+                    builds.
+                </li>
+            </ul>
+        </section>
+    </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/xdoc/download_vfs.xml b/VFS-2.0-RC1/src/site/xdoc/download_vfs.xml
new file mode 100644
index 0000000..e26f15b
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/download_vfs.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<!--
+ +======================================================================+
+ |****                                                              ****|
+ |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|
+ |****                    DO NOT EDIT DIRECTLY                      ****|
+ |****                                                              ****|
+ +======================================================================+
+ | TEMPLATE FILE: download-page-template.xml                            |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ |                                                                      |
+ | 1) Re-generate using: mvn commons:download-page                      |
+ |                                                                      |
+ | 2) Set the following properties in the component's pom:              |
+ |    - commons.componentid (required, alphabetic, lower case)          |
+ |    - commons.release.version (required)                              |
+ |    - commons.binary.suffix (optional)                                |
+ |      (defaults to "-bin", set to "" for pre-maven2 releases)         |
+ |                                                                      |
+ | 3) Example Properties                                                |
+ |                                                                      |
+ |  <properties>                                                        |
+ |    <commons.componentid>math</commons.componentid>                   |
+ |    <commons.release.version>1.2</commons.release.version>            |
+ |  </properties>                                                       |
+ |                                                                      |
+ +======================================================================+
+-->
+<document>
+  <properties>
+    <title>Download Commons VFS</title>
+    <author email="dev@commons.apache.org">Commons Documentation Team</author>
+  </properties>
+  <body>
+    <section name="Download Commons VFS">
+    <subsection name="Using a Mirror">
+      <p>
+        We recommend you use a mirror to download our release
+        builds, but you <strong>must</strong> verify the integrity of
+        the downloaded files using signatures downloaded from our main 
+        distribution directories. Recent releases (48 hours) may not yet
+        be available from the mirrors.
+      </p>
+
+      <p>
+        You are currently using <b>[preferred]</b>.  If you
+        encounter a problem with this mirror, please select another
+        mirror.  If all mirrors are failing, there are <i>backup</i>
+        mirrors (at the end of the mirrors list) that should be
+        available.
+        <br></br>
+        [if-any logo]<a href="[link]"><img align="right" src="[logo]" border="0"></img></a>[end]
+      </p>
+
+      <form action="[location]" method="get" id="SelectMirror">
+        <p>
+          Other mirrors: 
+          <select name="Preferred">
+          [if-any http]
+            [for http]<option value="[http]">[http]</option>[end]
+          [end]
+          [if-any ftp]
+            [for ftp]<option value="[ftp]">[ftp]</option>[end]
+          [end]
+          [if-any backup]
+            [for backup]<option value="[backup]">[backup] (backup)</option>[end]
+          [end]
+          </select>
+          <input type="submit" value="Change"></input>
+        </p>
+      </form>
+
+      <p>
+        The <a href="http://www.apache.org/dist/commons/KEYS">KEYS</a>
+        link links to the code signing keys used to sign the product.
+        The <code>PGP</code> link downloads the OpenPGP compatible signature from our main site. 
+        The <code>MD5</code> link downloads the checksum from the main site.
+      </p>
+    </subsection>
+    </section>
+    <section name="Commons VFS 1.0 ">
+      <subsection name="Binaries">
+        <table>
+          <tr>
+              <td><a href="[preferred]/commons/vfs/binaries/commons-vfs-1.0.tar.gz">commons-vfs-1.0.tar.gz</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/binaries/commons-vfs-1.0.tar.gz.md5">md5</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/binaries/commons-vfs-1.0.tar.gz.asc">pgp</a></td>
+          </tr>
+          <tr>
+              <td><a href="[preferred]/commons/vfs/binaries/commons-vfs-1.0.zip">commons-vfs-1.0.zip</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/binaries/commons-vfs-1.0.zip.md5">md5</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/binaries/commons-vfs-1.0.zip.asc">pgp</a></td>
+          </tr>
+        </table>
+      </subsection>
+      <subsection name="Source">
+        <table>
+          <tr>
+              <td><a href="[preferred]/commons/vfs/source/commons-vfs-1.0-src.tar.gz">commons-vfs-1.0-src.tar.gz</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/source/commons-vfs-1.0-src.tar.gz.md5">md5</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/source/commons-vfs-1.0-src.tar.gz.asc">pgp</a></td>
+          </tr>
+          <tr>
+              <td><a href="[preferred]/commons/vfs/source/commons-vfs-1.0-src.zip">commons-vfs-1.0-src.zip</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/source/commons-vfs-1.0-src.zip.md5">md5</a></td>
+              <td><a href="http://www.apache.org/dist/commons/vfs/source/commons-vfs-1.0-src.zip.asc">pgp</a></td>
+          </tr>
+        </table>
+      </subsection>
+    </section>
+    <section name="Archives">
+        <p>
+          Older releases can be obtained from the archives.
+        </p>
+        <ul>
+          <li class="download"><a href="[preferred]/commons/vfs/">browse download area</a></li>
+          <li><a href="http://archive.apache.org/dist/commons/vfs/">archives...</a></li>
+        </ul>
+    </section>
+  </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/xdoc/filesystems.xml b/VFS-2.0-RC1/src/site/xdoc/filesystems.xml
new file mode 100644
index 0000000..73d5070
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/filesystems.xml
@@ -0,0 +1,592 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+
+    <properties>
+        <title>Supported File Systems</title>
+        <author email="adammurdoch@apache.org">Adam Murdoch</author>
+        <author email="imario@apache.org">Mario Ivankovits</author>
+    </properties>
+
+    <body>
+        <section name="Supported File Systems">
+            <p>Commons VFS currently supports the following file systems:</p>
+            <ul>
+                <li>
+                    <a href="#FTP">FTP</a>
+                </li>
+                <li>
+                    <a href="#Local Files">Local Files</a>
+                </li>
+                <li>
+                    <a href="#HTTP and HTTPS">HTTP and HTTPS</a>
+                </li>
+                <li>
+                    <a href="#SFTP">SFTP</a>
+                </li>
+                <li>
+                    <a href="#Temporary Files">Temporary Files</a>
+                </li>
+                <li>
+                    <a href="#Zip, Jar and Tar">Zip, Jar and Tar (uncompressed, tgz or tbz2)</a>
+                </li>
+                <li>
+                    <a href="#gzip and bzip2">gzip and bzip2</a>
+                </li>
+                <li>
+                    <a href="#res">res</a>
+                </li>
+                <li>
+                    <a href="#ram">ram</a>
+                </li>
+                <li>
+                    <a href="#mime">mime</a>
+                </li>
+                <li>
+                              <a href="#WebDAV">WebDAV</a><br />
+                        </li>
+            </ul>
+        </section>
+
+        <section name="Things from the sandbox">
+            <p>The following file systems are in development:</p>
+            <ul>
+                <li>
+                    <a href="#CIFS">CIFS</a>
+                </li>
+                <li>
+                    <a href="#mime">mime</a>
+                </li>
+            </ul>
+        </section>
+
+        <section name="Naming">
+
+            <p>All filenames are treated as URIs. One of the consequences of this is you have to encode the '%'
+                character using <code>%25</code>. <br />
+                Depending on the filesystem additional characters are encoded if needet. This is done automatically, but
+                might be reflected in the filename.
+                </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>file:///somedir/some%25file.txt</code>
+                </li>
+            </ul>
+            <p>
+               Many file systems accept a userid and password as part of the url. However, storing
+               a password in clear text in a file is usually unacceptable. To help with that
+               Commons VFS provides a mechanism to encrypt the password. It should be noted though,
+               that this is not completely secure since the password needs to be unencrypted
+               before Commons VFS can use it.
+            </p>
+            <p>
+               To create an encrypted password do:
+            </p>
+            <code> java -cp commons-vfs-2.0.jar org.apache.commons.vfs.util.EncryptUtil encrypt mypassword
+            </code>
+            <p>
+               where <i>mypassword</i> is the password you want to encrypt. The result of this will be a
+               single line of output containing uppercase hex characters.  For example,
+            </p>
+            <code>
+ java -cp commons-vfs-2.0.jar org.apache.commons.vfs.util.EncryptUtil encrypt WontUBee9
+ D7B82198B272F5C93790FEB38A73C7B8
+            </code>
+            <p>
+              Then cut the output returned and paste it into the URL as:
+            </p>
+            <code>
+ https://testuser:{D7B82198B272F5C93790FEB38A73C7B8}@myhost.com/svn/repos/vfstest/trunk
+            </code>
+            <p>
+               VFS treats a password enclosed in {} as being encrypted and will decrypt the password
+               before using it.
+            </p>
+        </section>
+
+        <section name="Local Files">
+
+            <p>Provides access to the files on the local physical file system.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>[file://]
+                    <i>absolute-path</i>
+                </code>
+            </p>
+
+            <p>
+                Where
+                <code>
+                    <i>absolute-path</i>
+                </code> is a valid absolute
+                file name for the local platform.  UNC names are supported
+                under Windows.
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>file:///home/someuser/somedir</code>
+                </li>
+                <li>
+                    <code>file:///C:/Documents and Settings</code>
+                </li>
+                <li>
+                    <code>file://///somehost/someshare/afile.txt</code>
+                </li>
+                <li>
+                    <code>/home/someuser/somedir</code>
+                </li>
+                <li>
+                    <code>c:\program files\some dir</code>
+                </li>
+                <li>
+                    <code>c:/program files/some dir</code>
+                </li>
+            </ul>
+        </section>
+
+        <section name="Zip, Jar and Tar">
+
+            <p>Provides read-only access to the contents of Zip, Jar and Tar files.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>zip://
+                    <i>arch-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                <code>jar://
+                    <i>arch-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                <code>tar://
+                    <i>arch-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                <code>tgz://
+                    <i>arch-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                <code>tbz2://
+                    <i>arch-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                Where
+                <code>arch-file-uri</code> refers to a file of any
+                supported type, including other zip files.  Note: if you would like
+                to use the ! as normal character it must be escaped
+                using <code>%21</code>.<br />
+                <code>tgz</code> and <code>tbz2</code> are convenience for <code>tar:gz</code> and <code>tar:bz2</code>.
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>jar:../lib/classes.jar!/META-INF/manifest.mf</code>
+                </li>
+                <li>
+                    <code>zip:http://somehost/downloads/somefile.zip</code>
+                </li>
+                <li>
+                    <code>jar:zip:outer.zip!/nested.jar!/somedir</code>
+                </li>
+                <li>
+                    <code>jar:zip:outer.zip!/nested.jar!/some%21dir</code>
+                </li>
+                <li>
+                    <code>tar:gz:http://anyhost/dir/mytar.tar.gz!/mytar.tar!/path/in/tar/README.txt</code>
+                </li>
+                <li>
+                    <code>tgz:file://anyhost/dir/mytar.tgz!/somepath/somefile</code>
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="gzip and bzip2">
+
+            <p>Provides read-only access to the contents of gzip and bzip2 files.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>gz://
+                    <i>compressed-file-uri</i>
+                </code>
+            </p>
+            <p>
+                <code>bz2://
+                    <i>compressed-file-uri</i>
+                </code>
+            </p>
+
+            <p>
+                Where
+                <code>compressed-file-uri</code> refers to a file of any
+                supported type. There is no need to add a ! part to the uri if
+                you read the content of the file you always will get the uncompressed
+                version.
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>gz:/my/gz/file.gz</code>
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="HTTP and HTTPS">
+
+            <p>Provides access to files on an HTTP server.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>http://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                <code>https://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+            <p>
+                 <b>File System Options</b>
+                 <ul>
+                   <li><b>proxyHost</b> The proxy host to connect through.</li>
+                   <li><b>proxyPort</b> The proxy port to use.</li>
+                   <li><b>cookies</b> An array of Cookies to add to the request.</li>
+                   <li><b>maxConnectionsPerHost</b> The maximum number of connections allowed to
+                   a specific host and port. The default is 5.</li>
+                   <li><b>maxTotalConnections</b> The maximum number of connections allowed to
+                   all hosts. The default is 50.</li>
+                 </ul>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>http://somehost:8080/downloads/somefile.jar</code>
+                </li>
+                <li>
+                    <code>http://myusername@somehost/index.html</code>
+                </li>
+            </ul>
+        </section>
+
+        <section name="WebDAV">
+
+            <p>Provides access to files on a WebDAV server.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>webdav://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>File System Options</b>
+                <ul>
+                  <li><b>versioning</b> true if versioning should be enabled</li>
+                  <li><b>creatorName</b> the user name to be identified with changes to a file. If
+                      not set the user name used to authenticate will be used.</li>
+                </ul>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>webdav://somehost:8080/dist</code>
+                </li>
+            </ul>
+        </section>
+
+        <section name="FTP">
+
+            <p>Provides access to the files on an FTP server.</p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>ftp://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>ftp://myusername:mypassword@somehost/pub/downloads/somefile.tgz</code>
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="SFTP">
+
+            <p>
+                Provides access to the files on an SFTP server (that is, an SSH
+                or SCP server).
+            </p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>sftp://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+            <ul>
+                <li>
+                    <code>sftp://myusername:mypassword@somehost/pub/downloads/somefile.tgz</code>
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="CIFS">
+
+            <p>
+                Provides access to the files on a CIFS server, such as
+                a Samba server, or a Windows share.
+            </p>
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>smb://[
+                    <i>username</i>[:
+                    <i>password</i>]@]
+                    <i>hostname</i>[:
+                    <i>port</i>][
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+
+            <ul>
+                <li>
+                    <code>smb://somehost/home</code>
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="Temporary Files">
+
+            <p>
+                Provides access to a temporary file system, or scratchpad,
+                that is deleted when Commons VFS shuts down.  The temporary file
+                system is backed by a local file system.
+            </p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>tmp://[
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+
+            <ul>
+                <li>
+                    <code>tmp://dir/somefile.txt</code>
+                </li>
+            </ul>
+        </section>
+
+        <section name="res">
+
+            <p>
+                This is not really a filesystem, it just tries to lookup a resource using javas <code>ClassLoader.getResource()</code>
+                and creates a VFS url for further processing.
+            </p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>res://[
+                    <i>path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+
+            <ul>
+                <li>
+                    <code>res:path/in/classpath/image.png</code><br/>
+                    might result in
+                    <code>jar:file://my/path/to/images.jar!/path/in/classpath/image.png</code><br/>
+                </li>
+            </ul>
+        </section>
+
+        <section name="ram">
+
+            <p>
+                A filesystem which stores all the data in memory.
+                You can configure the max size and a predicate (FileSelector). The predicate will be used to check if
+                it is allowed to add a given file.
+            </p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>ram://[
+                    <i>path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+
+            <ul>
+                <li>
+                    <code>ram:///any/path/to/file.txt</code>
+                </li>
+            </ul>
+        </section>
+
+        <section name="mime">
+
+            <p>
+                This filesystem can read mails and its attachements like archives.<br />
+                If a part in the parsed mail has no name, a dummy name will be generated.
+                The dummy name is: _body_part_X where X will be replaced by the part number.
+            </p>
+
+            <p>
+                <b>URI Format</b>
+            </p>
+
+            <p>
+                <code>mime://
+                    <i>mime-file-uri</i>[!
+                    <i>absolute-path</i>]
+                </code>
+            </p>
+
+            <p>
+                <b>Examples</b>
+            </p>
+
+            <ul>
+                <li>
+                    <code>mime:file:///your/path/mail/anymail.mime!/</code>
+                </li>
+                <li>
+                    <code>mime:file:///your/path/mail/anymail.mime!/filename.pdf</code>
+                </li>
+                <li>
+                    <code>mime:file:///your/path/mail/anymail.mime!/_body_part_0</code>
+                </li>
+            </ul>
+        </section>
+
+    </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/xdoc/index.xml b/VFS-2.0-RC1/src/site/xdoc/index.xml
new file mode 100644
index 0000000..83511f2
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/index.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<document>
+    <properties>
+        <title>Commons Virtual File System</title>
+        <author email="jstrachan@apache.org">James Strachan</author>
+    </properties>
+
+    <body>
+        <section name="Commons Virtual File System">
+
+            <p>
+                Commons VFS provides a single API for accessing
+                various different file systems. It presents a uniform view of
+                the files from various different sources, such as the files on
+                local disk, on an HTTP server, or inside a Zip archive.
+            </p>
+
+            <p>Some of the features of Commons VFS are:</p>
+            <ul>
+                <li>
+                    A single consistent API for accessing files of different
+                    types.
+                </li>
+                <li>Support for numerous
+                    <a href="filesystems.html">file system types</a>
+                    .
+                </li>
+                <li>
+                    Caching of file information. Caches information in-JVM,
+                    and optionally can cache remote file information on the
+                    local file system.
+                </li>
+                <li>Event delivery.</li>
+                <li>
+                    Support for logical file systems made up of files from
+                    various different file systems.
+                </li>
+                <li>
+                    Utilities for integrating Commons VFS into applications,
+                    such as a VFS-aware ClassLoader and URLStreamHandlerFactory.
+                </li>
+                <li>A set of VFS-enabled
+                    <a href="anttasks.html">Ant tasks</a>
+                    .
+                </li>
+            </ul>
+
+        </section>
+
+        <section name="News">
+            <p>
+                VFS is split into core, examples and sandbox now.
+            </p>
+            <p>
+                Due to some technical reasons we had to move the jcifs (smb) filesystem to
+                the sandbox. So if you need one of these filesystems you have to build VFS manually.
+            </p>
+            <p>
+                To build VFS, it will be best to check-it-out from svn and use maven 2 to
+                build.
+            </p>
+            <p>
+                And - we have a new filesystem: mime (read only for sure)<br/>
+                This filesystem allows you to read e-mails like archives, e.g. the attachments are the
+                children of the mail itself.<br />
+                You'll find it in our sandbox.
+            </p>
+            <p>
+                Also notice that we now have a "3rd party plugins" page. It will list all external
+                plugins available for VFS.<br />
+                You have such a beast - and will get listed? Just drop me a mail: imario -at- apache.org
+            </p>
+        </section>
+
+    </body>
+</document>
+
diff --git a/VFS-2.0-RC1/src/site/xdoc/issue-tracking.xml b/VFS-2.0-RC1/src/site/xdoc/issue-tracking.xml
new file mode 100644
index 0000000..fe79bd8
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/issue-tracking.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<!--
+ +======================================================================+
+ |****                                                              ****|
+ |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|
+ |****                    DO NOT EDIT DIRECTLY                      ****|
+ |****                                                              ****|
+ +======================================================================+
+ | TEMPLATE FILE: issue-tracking-template.xml                           |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ |                                                                      |
+ | 1) Re-generate using: mvn commons:jira-page                          |
+ |                                                                      |
+ | 2) Set the following properties in the component's pom:              |
+ |    - commons.jira.id  (required, alphabetic, upper case)             |
+ |    - commons.jira.pid (required, numeric)                            |
+ |                                                                      |
+ | 3) Example Properties                                                |
+ |                                                                      |
+ |  <properties>                                                        |
+ |    <commons.jira.id>MATH</commons.jira.id>                           |
+ |    <commons.jira.pid>12310485</commons.jira.pid>                     |
+ |  </properties>                                                       |
+ |                                                                      |
+ +======================================================================+
+-->
+<document>
+  <properties>
+    <title>Commons VFS Issue tracking</title>
+    <author email="dev@commons.apache.org">Commons Documentation Team</author>
+  </properties>
+  <body>
+
+    <section name="Commons VFS Issue tracking">
+      <p>
+      Commons VFS uses <a href="http://issues.apache.org/jira/">ASF JIRA</a> for tracking issues.
+      See the <a href="http://issues.apache.org/jira/browse/VFS">Commons VFS JIRA project page</a>.
+      </p>
+
+      <p>
+      To use JIRA you may need to <a href="http://issues.apache.org/jira/secure/Signup!default.jspa">create an account</a>
+      (if you have previously created/updated Commons issues using Bugzilla an account will have been automatically
+      created and you can use the <a href="http://issues.apache.org/jira/secure/ForgotPassword!default.jspa">Forgot Password</a>
+      page to get a new password).
+      </p>
+
+      <p>
+      If you would like to report a bug, or raise an enhancement request with
+      Commons VFS please do the following:
+      <ol>
+        <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&amp;pid=12310495&amp;sorter/field=issuekey&amp;sorter/order=DESC&amp;status=1&amp;status=3&amp;status=4">Search existing open bugs</a>.
+            If you find your issue listed then please add a comment with your details.</li>
+        <li><a href="mail-lists.html">Search the mailing list archive(s)</a>.
+            You may find your issue or idea has already been discussed.</li>
+        <li>Decide if your issue is a bug or an enhancement.</li>
+        <li>Submit either a <a href="http://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12310495&amp;issuetype=1&amp;priority=4&amp;assignee=-1">bug report</a>
+            or <a href="http://issues.apache.org/jira/secure/CreateIssueDetails!init.jspa?pid=12310495&amp;issuetype=4&amp;priority=4&amp;assignee=-1">enhancement request</a>.</li>
+      </ol>
+      </p>
+
+      <p>
+      Please also remember these points:
+      <ul>
+        <li>the more information you provide, the better we can help you</li>
+        <li>test cases are vital, particularly for any proposed enhancements</li>
+        <li>the developers of Commons VFS are all unpaid volunteers</li>
+      </ul>
+      </p>
+
+      <p>
+      For more information on subversion and creating patches see the
+      <a href="http://www.apache.org/dev/contributors.html">Apache Contributors Guide</a>.
+      </p>
+
+      <p>
+      You may also find these links useful:
+      <ul>
+        <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&amp;pid=12310495&amp;sorter/field=issuekey&amp;sorter/order=DESC&amp;status=1&amp;status=3&amp;status=4">All Open Commons VFS bugs</a></li>
+        <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&amp;pid=12310495&amp;sorter/field=issuekey&amp;sorter/order=DESC&amp;status=5&amp;status=6">All Resolved Commons VFS bugs</a></li>
+        <li><a href="http://issues.apache.org/jira/secure/IssueNavigator.jspa?reset=true&amp;pid=12310495&amp;sorter/field=issuekey&amp;sorter/order=DESC">All Commons VFS bugs</a></li>
+      </ul>
+      </p>
+    </section>
+  </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/xdoc/mail-lists.xml b/VFS-2.0-RC1/src/site/xdoc/mail-lists.xml
new file mode 100644
index 0000000..3700a65
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/mail-lists.xml
@@ -0,0 +1,202 @@
+<?xml version="1.0"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<!--
+ +======================================================================+
+ |****                                                              ****|
+ |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|
+ |****                    DO NOT EDIT DIRECTLY                      ****|
+ |****                                                              ****|
+ +======================================================================+
+ | TEMPLATE FILE: mail-lists-template.xml                               |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ |                                                                      |
+ | 1) Re-generate using: mvn commons:mail-page                          |
+ |                                                                      |
+ | 2) Set the following properties in the component's pom:              |
+ |    - commons.componentid (required, alphabetic, lower case)          |
+ |                                                                      |
+ | 3) Example Properties                                                |
+ |                                                                      |
+ |  <properties>                                                        |
+ |    <commons.componentid>math</commons.componentid>                   |
+ |  </properties>                                                       |
+ |                                                                      |
+ +======================================================================+
+-->
+<document>
+  <properties>
+    <title>Commons VFS Mailing Lists</title>
+    <author email="dev@commons.apache.org">Commons Documentation Team</author>
+  </properties>
+  <body>
+
+    <section name="Overview">
+      <p>
+        <a href="index.html">Commons VFS</a> shares mailing lists with all the other 
+        <a href="http://commons.apache.org/components.html">Commons Components</a>.
+        To make it easier for people to only read messages related to components they are interested in,
+        the convention in Commons is to prefix the subject line of messages with the component's name,
+        for example:
+        <ul>
+          <li>[vfs] Problem with the ...</li>
+        </ul>
+      </p>
+      <p>
+        Questions related to the usage of Commons VFS should be posted to the
+        <a href="http://mail-archives.apache.org/mod_mbox/commons-user/">User List</a>.
+        <br />
+        The <a href="http://mail-archives.apache.org/mod_mbox/commons-dev/">Developer List</a>
+        is for questions and discussion related to the development of Commons VFS.
+        <br />
+        Please do not cross-post; developers are also subscribed to the user list.
+      </p>
+      <p>
+        <strong>Note:</strong> please don't send patches or attachments to any of the mailing lists.
+        Patches are best handled via the <a href="issue-tracking.html">Issue Tracking</a> system. 
+        Otherwise, please upload the file to a public server and include the URL in the mail. 
+      </p>
+    </section>
+
+    <section name="Commons VFS Mailing Lists">
+      <p>
+        <strong>Please prefix the subject line of any messages for <a href="index.html">Commons VFS</a>
+        with <i>[vfs]</i></strong> - <i>thanks!</i>
+        <br />
+        <br />
+      </p>
+
+      <table>
+        <tr>
+          <th>Name</th>
+          <th>Subscribe</th>
+          <th>Unsubscribe</th>
+          <th>Post</th>
+          <th>Archive</th>
+          <th>Other Archives</th>
+        </tr>
+
+
+        <tr>
+          <td>
+            <strong>Commons User List</strong>
+            <br /><br />
+            Questions on using Commons VFS.
+            <br /><br />
+          </td>
+          <td><a href="mailto:user-subscribe@commons.apache.org">Subscribe</a></td>
+          <td><a href="mailto:user-unsubscribe@commons.apache.org">Unsubscribe</a></td>
+          <td><a href="mailto:user@commons.apache.org?subject=[vfs]">Post</a></td>
+          <td><a href="http://mail-archives.apache.org/mod_mbox/commons-user/">mail-archives.apache.org</a></td>
+          <td><a href="http://markmail.org/list/org.apache.commons.users/">markmail.org</a><br />
+              <a href="http://www.mail-archive.com/user@commons.apache.org/">www.mail-archive.com</a><br />
+              <a href="http://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+          </td>
+        </tr>
+
+
+        <tr>
+          <td>
+            <strong>Commons Developer List</strong>
+            <br /><br />
+            Discussion of development of Commons VFS.
+            <br /><br />
+          </td>
+          <td><a href="mailto:dev-subscribe@commons.apache.org">Subscribe</a></td>
+          <td><a href="mailto:dev-unsubscribe@commons.apache.org">Unsubscribe</a></td>
+          <td><a href="mailto:dev@commons.apache.org?subject=[vfs]">Post</a></td>
+          <td><a href="http://mail-archives.apache.org/mod_mbox/commons-dev/">mail-archives.apache.org</a></td>
+          <td><a href="http://markmail.org/list/org.apache.commons.dev/">markmail.org</a><br />
+              <a href="http://www.mail-archive.com/dev@commons.apache.org/">www.mail-archive.com</a><br />
+              <a href="http://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+          </td>
+        </tr>
+
+
+        <tr>
+          <td>
+            <strong>Commons Issues List</strong>
+            <br /><br />
+            Only for e-mails automatically generated by the <a href="issue-tracking.html">issue tracking</a> system.
+            <br /><br />
+          </td>
+          <td><a href="mailto:issues-subscribe@commons.apache.org">Subscribe</a></td>
+          <td><a href="mailto:issues-unsubscribe@commons.apache.org">Unsubscribe</a></td>
+          <td><i>read only</i></td>
+          <td><a href="http://mail-archives.apache.org/mod_mbox/commons-issues/">mail-archives.apache.org</a></td>
+          <td><a href="http://markmail.org/list/org.apache.commons.issues/">markmail.org</a><br />
+              <a href="http://www.mail-archive.com/issues@commons.apache.org/">www.mail-archive.com</a>
+          </td>
+        </tr>
+
+
+        <tr>
+          <td>
+            <strong>Commons Commits List</strong>
+            <br /><br />
+            Only for e-mails automatically generated by the <a href="source-repository.html">source control</a> sytem.
+            <br /><br />
+          </td>
+          <td><a href="mailto:commits-subscribe@commons.apache.org">Subscribe</a></td>
+          <td><a href="mailto:commits-unsubscribe@commons.apache.org">Unsubscribe</a></td>
+          <td><i>read only</i></td>
+          <td><a href="http://mail-archives.apache.org/mod_mbox/commons-commits/">mail-archives.apache.org</a></td>
+          <td><a href="http://markmail.org/list/org.apache.commons.commits/">markmail.org</a><br />
+              <a href="http://www.mail-archive.com/commits@commons.apache.org/">www.mail-archive.com</a>
+          </td>
+        </tr>
+
+      </table>
+
+    </section>
+    <section name="Apache Mailing Lists">
+      <p>
+        Other mailing lists which you may find useful include:
+      </p>
+
+      <table>
+        <tr>
+          <th>Name</th>
+          <th>Subscribe</th>
+          <th>Unsubscribe</th>
+          <th>Post</th>
+          <th>Archive</th>
+          <th>Other Archives</th>
+        </tr>
+        <tr>
+          <td>
+            <strong>Apache Announce List</strong>
+            <br /><br />
+            General announcements of Apache project releases.
+            <br /><br />
+          </td>
+          <td><a class="externalLink" href="mailto:announce-subscribe@apache.org">Subscribe</a></td> 
+          <td><a class="externalLink" href="mailto:announce-unsubscribe@apache.org">Unsubscribe</a></td> 
+          <td><i>read only</i></td>
+          <td><a class="externalLink" href="http://mail-archives.apache.org/mod_mbox/www-announce/">mail-archives.apache.org</a></td> 
+          <td><a class="externalLink" href="http://markmail.org/list/org.apache.announce/">markmail.org</a><br />
+              <a class="externalLink" href="http://old.nabble.com/Apache-News-and-Announce-f109.html">old.nabble.com</a><br />
+              <a class="externalLink" href="http://www.mail-archive.com/announce@apache.org/">www.mail-archive.com</a><br />
+              <a class="externalLink" href="http://news.gmane.org/gmane.comp.apache.announce">news.gmane.org</a>
+          </td>
+        </tr>
+      </table>
+
+    </section>
+  </body>
+</document>
diff --git a/VFS-2.0-RC1/src/site/xdoc/testing.xml b/VFS-2.0-RC1/src/site/xdoc/testing.xml
new file mode 100644
index 0000000..af206ce
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/testing.xml
@@ -0,0 +1,289 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+    <properties>
+        <title>Running the Tests</title>
+        <author email="rgoers@apache.org">Ralph Goers</author>
+    </properties>
+
+    <body>
+        <section name="Running the tests">
+            <p>
+                This page details how to setup the tests for the various providers and then
+                run them with Maven 2.
+            </p>
+            <p>
+                The tests were run on Mac OS/X 10.5. The tests requiring a remote repository
+                were pointed to a second machine running Kubuntu 7.10 and the various servers
+                that can be installed from the system administration tool. The only exception
+                to this is that the WebDAV and Http support was testing using Day CRX 1.4 as
+                the server.
+            </p>
+
+            <subsection name="Getting Started">
+                <p>
+                    First, from the root directory of the project, run <code>mvn install</code>.
+                    This will compile all the source and test source and then run all the tests
+                    for providers that use the local file system.
+                </p>
+            </subsection>
+
+            <subsection name="Setting up the remote server">
+                <p>
+                    Each remote service needs to have the test data placed within it's "repository".
+                    After running the maven build, the test data can be found in
+                    core/target/test-data. Each service may require a userid and password to be
+                    created. For example, to run the ftp test on a Linux system a user should be
+                    created and the test data placed within that user's home directory. See the
+                    following sections for details on each service.
+                </p>
+                <p>
+                    Each repository should contain the following list of files for the tests to
+                    complete successfully.
+                </p>
+                <source><![CDATA[
+write-tests
+read-tests
+read-tests/file1.txt
+read-tests/dir1
+read-tests/dir1/file1.txt
+read-tests/dir1/file2.txt
+read-tests/dir1/file3.txt
+read-tests/dir1/subdir1
+read-tests/dir1/subdir1/file1.txt
+read-tests/dir1/subdir1/file2.txt
+read-tests/dir1/subdir1/file3.txt
+read-tests/dir1/subdir2
+read-tests/dir1/subdir2/file1.txt
+read-tests/dir1/subdir2/file2.txt
+read-tests/dir1/subdir2/file3.txt
+read-tests/dir1/subdir3
+read-tests/dir1/subdir3/file1.txt
+read-tests/dir1/subdir3/file2.txt
+read-tests/dir1/subdir3/file3.txt
+read-tests/empty.txt
+read-tests/file%.txt
+code
+code/sealed
+code/sealed/AnotherClass.class
+code/ClassToLoad.class]]></source>
+            </subsection>
+
+            <subsection name="Apache 2 Webserver">
+                <p>
+                    Create a user on the system
+                </p>
+                <ol>
+                    <li>Create a user 'vfsusr' with password 'vfs/%\te:st' and home directory '/home/vfsusr'
+                        <br/>
+                        <source><![CDATA[
+useradd -p vfsusr -m vfsusr]]></source>
+                    </li>
+                    <li>In vfsuser's home directory create the directories
+                        <ol>
+                            <li>vfstest</li>
+                            <li>vfstest/write-tests</li>
+                        </ol>
+                    </li>
+                    <li>Copy the test data into the vfstest directory</li>
+                    <li>Create a symbolic link at '/vfstest' to /home/vfsuser/vfstest<br />
+                        <source><![CDATA[
+ln -s /vfstest /home/vfsusr/vfstest]]></source>
+                    </li>
+                    <li>Create a file named '/etc/apache2/conf.d/vfstest.conf' with this content<br />
+                        <source><![CDATA[
+#
+# VFSTEST
+#
+Alias /vfstest /vfstest/
+
+DAVLockDB /var/lib/apache2/dav.lockDB
+DAVMinTimeout 600
+
+<Directory /vfstest>
+    Options None
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+<Location />
+        DAV On
+        Options Indexes MultiViews
+        AllowOverride None
+
+        AuthType Basic
+        AuthName vfstest_zone
+        AuthUserFile /etc/apache2/passwd
+        <Limit PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
+                Require user vfsusr
+        </Limit>
+</Location>]]></source>
+                    </li>
+                    <li>change the permission on
+                        <source><![CDATA[
+chown vfsusr.users /var/lib/apache2
+                        ]]></source>
+                    </li>
+                    <li>Activate the WebDAV module by adding 'dav' and 'dav_fs' to the list of modules in '/etc/sysconfig/apache2'. e.g <br/>
+                        <source><![CDATA[
+APACHE_MODULES="access actions alias auth auth_dbm autoindex cgi dir env expires include log_config
+mime negotiation setenvif ssl suexec userdir php4 php5 dav dav_fs"]]></source>
+                    </li>
+                    <li>Setup the webserver to use user-id 'vfsusr' and group 'users'. This can be done by changing the file '/etc/apache2/uid.conf'<br />
+                        <source><![CDATA[
+User vfsusr
+Group users]]></source>
+                    </li>
+                    <li>Create the VFS user to access the Webdav resource<br />
+                        <source><![CDATA[
+htpasswd2 -cmb /etc/apache2/passwd  vfsusr 'vfstest']]></source>
+                    </li>
+                    <li>Add the following to profiles section of settings.xml in the Maven home
+                        directory. Modify the urls to match your setup.
+                        <source><![CDATA[
+   <profile>
+      <id>http</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <test.http.uri>http://vfsusr:vfstest@192.168.10.133:80/vfstest/test-data</test.http.uri>
+      </properties>
+    </profile>
+    <profile>
+      <id>webdav</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <test.webdav.uri>webdav://vfsusr:vfstest@192.168.10.133:80/vfstest/test-data</test.webdav.uri>
+      </properties>
+    </profile>]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="Day CRX or Apache Jackrabbit">
+                <ol>
+                    <li>Use Windows Explorer, Mac Finder or a similar tool to connect to the
+                        repository.</li>
+                    <li>Create a vfstest directory</li>
+                    <li>Drag the test-data from Explorer/Finder window to the repository window to
+                        copy the files to the vfstest directory in the repository</li>
+                    <li>Add the following to profiles section of settings.xml in the Maven home
+                        directory. Modify the urls to match your setup.
+                        <source><![CDATA[
+   <profile>
+      <id>http</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <test.http.uri>http://admin:admin@192.168.10.133:7402/vfstest/test-data</test.http.uri>
+      </properties>
+    </profile>
+    <profile>
+      <id>webdav</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <test.webdav.uri>webdav://admin:admin@192.168.10.133:7402/vfstest/test-data</test.webdav.uri>
+      </properties>
+    </profile>]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="Samba 3">
+                <ol>
+                    <li>Create a share 'vfsusr'<br />
+                        <source><![CDATA[
+[vfsusr]
+   comment = VFS Test Directory
+   path = /home/vfsusr
+   guest ok = yes
+   writable = yes]]></source>
+                    </li>
+                    <li>Setup a 'vfsusr' with password 'vfstest'<br />
+                        <source><![CDATA[
+smbpasswd -a vfsusr]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="ssh">
+                <ol>
+                    <li>In '/etc/ssh/sshd_config' ensure<br />
+                        <source><![CDATA[
+PasswordAuthentication yes]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="vsftp">
+                <ol>
+                    <li>Create a user 'vfsusr' with password 'vfstest' and home directory '/home/vfsusr'
+                        <br/>
+                        <source><![CDATA[
+useradd -p vfsusr -m vfsusr]]></source>
+                    </li>
+                    <li>In vfsuser's home directory create the directories
+                        <ol>
+                            <li>vfstest</li>
+                            <li>vfstest/write-tests</li>
+                        </ol>
+                    </li>
+                    <li>Copy the test data into the vfstest directory</li>
+                    <li>Ensure the server is not disabled in the xinetd configuration<br />
+                        Set <source>disable=no</source> in '/etc/xinetd.d/vsftpd'
+                    </li>
+
+                    <li>Setup the server config: '/etc/vsftpd.conf'<br/>
+                        <source><![CDATA[
+write_enable=YES
+local_enable=YES]]></source>
+
+                    <li>Add the following to profiles section of settings.xml in the Maven home
+                        directory. Modify the urls to match your setup.
+                        <source><![CDATA[
+    <profile>
+      <id>ftp</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <properties>
+        <test.ftp.uri>ftp://admin:admin@192.168.10.133/vfstest/test-data</test.ftp.uri>
+      </properties>
+    </profile>]]></source>
+                    </li>        </li>
+
+                </ol>
+            </subsection>
+
+            <subsection name="Running tests">
+                <p>
+                    Running tests simply requires that the appropriate profile be activated. For
+                    example, to run just the webdav test do
+                    <code>mvn -P webdav test -Dtest=WebdavProviderTestCase</code>. Multipe tests
+                    can be run by doing <code>mvn -P webdav -P http test</code>.
+                </p>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/src/site/xdoc/testserver.xml b/VFS-2.0-RC1/src/site/xdoc/testserver.xml
new file mode 100644
index 0000000..fd87366
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/testserver.xml
@@ -0,0 +1,248 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<document>
+    <properties>
+        <title>Setup a Testserver</title>
+        <author email="imario@apache.org">Mario Ivankovits</author>
+    </properties>
+
+    <body>
+        <section name="Testserver">
+            <p>
+                This documentation describes how to setup a VFS testserver needed during development for the junit
+                tests.
+            </p>
+            <p>
+                I tried to simplify things as good as I can, e.g. this setup uses for all server the same vfs work
+                directory.
+                Thus it is needed to setup apache to use user 'vfsusr' instead of 'wwwrun'.
+                <br/>
+                Based on this description it should be possible for you to avoid this "insecurity" if needed.
+            </p>
+            <p>
+                I created it during setup a fresh server based on the following components:
+
+                <ol>
+                    <li>SuSE Linux 9.3 Minimal Installation</li>
+                    <li>Apache 2 Webserver (apache2-2.0.53)</li>
+                    <li>Samba 3 (samba-3.0.12)</li>
+                    <li>ssh (openssh-3.9p1)</li>
+                    <li>vsftp (vsftpd-2.0.2-3)</li>
+                </ol>
+            </p>
+
+
+            <subsection name="System setup">
+                <ol>
+                    <li>You need maven to build the local test-data structure. This is done automatically during build of VFS.</li>
+                    <li>Create a user 'vfsusr' with password 'vfs/%\te:st' and home directory '/home/vfsusr'
+                        <br/>
+                        <source><![CDATA[
+useradd -p vfsusr -m vfsusr
+                    ]]></source>
+                    </li>
+                    <li>Create the directories
+                        <ol>
+                            <li>/vfstest</li>
+                            <li>/vfstest/write-tests</li>
+                        </ol>
+                        and copy from your local 'target/test-data' the directories
+                        <source>code,read-tests</source> into it.<br />
+                        Now your structure looks like this:<br />
+                        <source><![CDATA[
+/vfstest
+/vfstest/write-tests
+/vfstest/read-tests
+/vfstest/read-tests/emptydir
+/vfstest/read-tests/file1.txt
+/vfstest/read-tests/dir1
+/vfstest/read-tests/dir1/file1.txt
+/vfstest/read-tests/dir1/file2.txt
+/vfstest/read-tests/dir1/file3.txt
+/vfstest/read-tests/dir1/subdir1
+/vfstest/read-tests/dir1/subdir1/file1.txt
+/vfstest/read-tests/dir1/subdir1/file2.txt
+/vfstest/read-tests/dir1/subdir1/file3.txt
+/vfstest/read-tests/dir1/subdir2
+/vfstest/read-tests/dir1/subdir2/file1.txt
+/vfstest/read-tests/dir1/subdir2/file2.txt
+/vfstest/read-tests/dir1/subdir2/file3.txt
+/vfstest/read-tests/dir1/subdir3
+/vfstest/read-tests/dir1/subdir3/file1.txt
+/vfstest/read-tests/dir1/subdir3/file2.txt
+/vfstest/read-tests/dir1/subdir3/file3.txt
+/vfstest/read-tests/empty.txt
+/vfstest/read-tests/file%.txt
+/vfstest/code
+/vfstest/code/sealed
+/vfstest/code/sealed/AnotherClass.class
+/vfstest/code/ClassToLoad.class
+                    ]]></source>
+                    </li>
+                    <li>Setup a symbolic link to '/vfstest'<br />
+                        <source><![CDATA[
+ln -s /vfstest /home/vfsusr/vfstest
+                    ]]></source>
+                    </li>
+                    <li>Set permissions
+                        <br/>
+                        <source><![CDATA[
+find /vfstest -print0 | xargs -0 chown vfsusr.users
+                    ]]></source>
+                    </li>
+                    <li>After you followed the steps below and setup the server ensure they
+                        are activated and running.<br />
+                        This is only needed if you installed a fresh system. Otherwise simply restart them.
+                        <br/>
+                        <source><![CDATA[
+insserv xinetd
+insserv apache2
+insserv smb
+insserv nmb
+/etc/rc.d/xinetd restart
+/etc/rc.d/apache2 restart
+/etc/rc.d/smb restart
+/etc/rc.d/nmb restart
+                        ]]></source>
+                        </li>
+                </ol>
+            </subsection>
+
+            <subsection name="Apache 2 Webserver">
+                <ol>
+                    <li>Create a file named '/etc/apache2/conf.d/vfstest.conf' with this content<br />
+                        <source><![CDATA[
+#
+# VFSTEST
+#
+Alias /vfstest /vfstest/
+
+DAVLockDB /var/lib/apache2/dav.lockDB
+DAVMinTimeout 600
+
+<Directory /vfstest>
+    Options None
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+<Location />
+        DAV On
+        Options Indexes MultiViews
+        AllowOverride None
+
+        AuthType Basic
+        AuthName vfstest_zone
+        AuthUserFile /etc/apache2/passwd
+        <Limit PUT POST DELETE PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
+                Require user vfsusr
+        </Limit>
+</Location>
+                            ]]></source>
+                    </li>
+                    <li>change the permission on
+                        <source><![CDATA[
+chown vfsusr.users /var/lib/apache2
+                        ]]></source>
+                    </li>
+                    <li>Activate the WebDAV module by adding 'dav' and 'dav_fs' to the list of modules in '/etc/sysconfig/apache2'. e.g <br/>
+                        <source><![CDATA[
+APACHE_MODULES="access actions alias auth auth_dbm autoindex cgi dir env expires include log_config
+mime negotiation setenvif ssl suexec userdir php4 php5 dav dav_fs"
+                            ]]></source>
+                    </li>
+                    <li>Setup the webserver to use user-id 'vfsusr' and group 'users'. This can be done by changing the file '/etc/apache2/uid.conf'<br />
+                        <source><![CDATA[
+User vfsusr
+Group users
+                        ]]></source>
+                    </li>
+                    <li>Create the VFS user to access the Webdav resource<br />
+                        <source><![CDATA[
+htpasswd2 -cmb /etc/apache2/passwd  vfsusr 'vfs/%\te:st'
+                        ]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="Samba 3">
+                <ol>
+                    <li>Create a share 'vfsusr'<br />
+                        <source><![CDATA[
+[vfsusr]
+   comment = VFS Test Directory
+   path = /home/vfsusr
+   guest ok = yes
+   writable = yes
+                        ]]></source>
+                    </li>
+                    <li>Setup a 'vfsusr' with password 'vfs/%\te:st'<br />
+                        <source><![CDATA[
+smbpasswd -a vfsusr
+                        ]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="ssh">
+                <ol>
+                    <li>In '/etc/ssh/sshd_config' ensure<br />
+                        <source><![CDATA[
+PasswordAuthentication yes
+                        ]]></source>
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="vsftp">
+                <ol>
+                    <li>Ensure the server is not disabled in the xinetd configuration<br />
+                        Set <source>disable=no</source> in '/etc/xinetd.d/vsftpd'
+                    </li>
+
+                    <li>Setup the server config: '/etc/vsftpd.conf'<br/>
+                        <source>
+write_enable=YES
+local_enable=YES
+                        </source>
+
+                    </li>
+                </ol>
+            </subsection>
+
+            <subsection name="Tests">
+                Now we are finished and you can try to activate the tests by
+                <ol>
+                    <li>reactivate the tests in 'build.xml'.<br/>
+                    Search for <code><![CDATA[<!-- tests disabled -->]]></code> and comment the exclude.</li>
+                    <source><![CDATA[
+<!-- tests disabled
+<exclude name="**/*.java">
+</exclude>
+ -->
+                    ]]></source>
+                    <li>or use the class org.apache.commons.vfs.RunTest where you have
+                        to adapt some properties at the top of the file and choose which test
+                        you would like to run by comment the others.<br />
+                        This is the way how I debug a failed testcase.
+                    </li>
+                </ol>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file
diff --git a/VFS-2.0-RC1/src/site/xdoc/todo.xml b/VFS-2.0-RC1/src/site/xdoc/todo.xml
new file mode 100644
index 0000000..4722c3b
--- /dev/null
+++ b/VFS-2.0-RC1/src/site/xdoc/todo.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+   
+         http://www.apache.org/licenses/LICENSE-2.0
+   
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<document>
+    <properties>
+        <title>TODO</title>
+        <author email="jstrachan@apache.org">James Strachan</author>
+        <author email="adammurdoch@apache.org">Adam Murdoch</author>
+        <author email="imario@apache.org">Mario Ivankovits</author>
+    </properties>
+
+    <body>
+        <section name="TODO">
+            <p>
+                The following is a list of items that need to be completed.
+                Contributions are welcome!
+            </p>
+
+            <subsection name="Release 1.1">
+                <ul>
+                    <li>moveTo should handle a directory move if it moves from a different filesystem.</li>
+                </ul>
+            </subsection>
+
+            <subsection name="Open">
+                <ul>
+                    <li>More documentation (status, file naming etc).</li>
+                    <li>Fix the
+                        <a href="task-list.html">TODO items</a> in the code.
+                    </li>
+                    <li>Add more providers:
+                        <ul>
+                            <li>rsync</li>
+                            <li>subversion</li>
+
+                            <li>nfs</li>
+                            <li>cvs</li>
+                            <li>jdbc filesystem</li>
+                            <li>xml filesystem</li>
+                            <li>jndi</li>
+                            <li>imap</li>
+                            <li>local mirror</li>
+                            <li>spidering http</li>
+                            <li>...</li>
+                        </ul>
+                    </li>
+                    <li>JNDI integration.</li>
+                    <li>Formalise the provider API.</li>
+                    <li>WebDAV Provider:
+                        <ul>
+                            <li>Add plain http support, and auto-detect dav resources.</li>
+                            <li>Add set last-modified.</li>
+                            <li>HTTPS</li>
+                        </ul>
+                    </li>
+                    <li>Zip/Jar Provider:
+                        <ul>
+                            <li>Extract an AbstractLayerFileSystem out of ZipFileSystem.</li>
+                            <li>
+                                Track changes to the parent layer.  Eg when the
+                                parent layer is deleted, mark all the files in the
+                                fs as 'does-not-exist'.
+                            </li>
+                            <li>Add support for writing to zip/jar files.</li>
+                        </ul>
+                    </li>
+                    <li>URL Provider:
+                        <ul>
+                            <li>Support attributes.</li>
+                        </ul>
+                    </li>
+                    <li>HTTP Provider:
+                        <ul>
+                            <li>Support attributes.</li>
+                            <li>HTTPS support.</li>
+                        </ul>
+                    </li>
+                    <li>
+                        The local disk caching mechanism also needs more work.  Needs
+                        to check last-modified time.  Replicator needs to be more
+                        configurable.
+                    </li>
+                    <li>Add persistent replicator.</li>
+                    <li>
+                        Finish support for junctions:  Make ancestors of a junction
+                        point visible, fire events when junction is added or removed,
+                        tests.
+                    </li>
+                    <li>
+                        Add support for federation (ie transparently crossing file
+                        system boundaries, such as drilling down into the contents
+                        of a Jar file).
+                    </li>
+                    <li>Add an equivalent of the fileScanner Jelly tag.</li>
+                    <li>
+                        Add an equivalent of Ant path, fileset, dirset, filelist, etc.
+                        Ideally, these can be abstracted into a single data type.
+                    </li>
+                    <li>
+                        Allow selectors, name mappers, and filters to be specified
+                        for the Ant tasks.
+                    </li>
+                    <li>Add capabilities to FileObject.</li>
+                    <li>Attributes and attribute schema.</li>
+                    <li>
+                        Handle file canonicalisation better (for cases like
+                        case-insensitive file systems, symbolic links, name mangling, etc).
+                    </li>
+                    <li>Add more selectors: XPath, Ant style, regular expression.</li>
+                    <li>Add adaptor (NodePointerFactory?) for use with JXpath.</li>
+                    <li>
+                        Add content-changed, attribute-changed, and move events to
+                        FileListener.  Maybe split into structure and content
+                        listeners.
+                    </li>
+                    <li>Get/set the file permissions.</li>
+                    <li>Automatically checksum and/or verify remote files.</li>
+                    <li>
+                        Look at adding native code for fine-grained control over
+                        permissions, file monitoring, faster moves, etc.  Must be
+                        optional - the thing should still build and run without the
+                        native code.
+                    </li>
+                </ul>
+            </subsection>
+        </section>
+
+        <section name="Library upgrades">
+            <p>
+                The following describes things I discovered during testing newer dependencies.
+            </p>
+
+            <subsection name="webdavlib 2.1">
+                <ul>
+                    <li>resource.listWebdavResources() do no longer list directories?<br />Figure out what to do</li>
+                </ul>
+            </subsection>
+
+        </section>
+    </body>
+</document>
\ No newline at end of file