[jboss-cvs] JBossAS SVN: r81475 - in projects/vfs/tags: 2.0.0.GA and 14 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Mon Nov 24 04:55:50 EST 2008


Author: alesj
Date: 2008-11-24 04:55:49 -0500 (Mon, 24 Nov 2008)
New Revision: 81475

Added:
   projects/vfs/tags/2.0.0.GA/
   projects/vfs/tags/2.0.0.GA/pom.xml
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/IterableTimedVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractExceptionHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/helpers/
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/ExceptionHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ExceptionHandlerTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/IterableTimedCacheTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/resources/vfs/context/file/nested/
   projects/vfs/tags/2.0.0.GA/src/test/resources/vfs/test/zipeinit.jar
Removed:
   projects/vfs/tags/2.0.0.GA/pom.xml
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java
   projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java
   projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
Log:
[maven-release-plugin]  copy for tag 2.0.0.GA

Copied: projects/vfs/tags/2.0.0.GA (from rev 80637, projects/vfs/branches/Branch_2_0)

Deleted: projects/vfs/tags/2.0.0.GA/pom.xml
===================================================================
--- projects/vfs/branches/Branch_2_0/pom.xml	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/pom.xml	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,122 +0,0 @@
-<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.jboss</groupId>
-    <artifactId>jboss-parent</artifactId>
-    <version>4</version>
-  </parent>
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>org.jboss</groupId>
-  <artifactId>jboss-vfs</artifactId>
-  <packaging>jar</packaging>
-  <version>2.0.0-SNAPSHOT</version>
-  <name>JBoss VFS</name>
-  <url>http://www.jboss.org</url>
-  <description>A VFS library</description>
- <scm>
-    <connection>scm:svn:http://anonsvn.jboss.org/repos/jbossas/projects/vfs/branches/Branch_2_0</connection>    
-    <developerConnection>scm:svn:https://svn.jboss.org/repos/jbossas/projects/vfs/branches/Branch_2_0</developerConnection>
-    <url>https://svn.jboss.org/repos/jbossas/projects/vfs/branches/Branch_2_0</url>
-  </scm>
-  <licenses>
-    <license>
-      <name>lgpl</name>
-      <url>http://repository.jboss.org/licenses/lgpl.txt</url>
-    </license>
-  </licenses>
-  <organization>
-    <name>JBoss, A division of Red Hat, Inc</name>
-    <url>http://www.jboss.org</url>
-  </organization>
-
-  <properties>
-    <version.jboss.common.core>2.2.9.GA</version.jboss.common.core>
-    <version.jboss.logging>2.0.5.GA</version.jboss.logging>
-    <version.jboss.test>1.1.0.GA</version.jboss.test>
-    <version.junit>4.4</version.junit>
-  </properties>
-
-  <build>
-    <sourceDirectory>src/main/java</sourceDirectory>
-    <testSourceDirectory>src/test/java</testSourceDirectory>
-    <finalName>${artifactId}</finalName>
-    <testResources>
-      <testResource>
-        <directory>src/test/resources</directory>
-      </testResource>
-    </testResources>
-    <plugins>
-      
-      <!-- define how we want compilation to take place
-        here, we accept most of the defaults but say that we want the
-        optimization flag set, and define the source and target to be 1.5,
-        these setting will be inherited by child projects -->
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-compiler-plugin</artifactId>
-        <version>2.0</version>
-        <configuration>
-          <debug>true</debug>
-          <source>1.5</source>
-          <target>1.5</target>
-        </configuration>
-      </plugin>
-      <!-- define that we wish to create src jars -->
-      <plugin>
-        <artifactId>maven-source-plugin</artifactId>
-        <inherited>true</inherited>
-        <executions>
-          <execution>
-            <goals>
-              <goal>jar</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.3.1</version>
-        <configuration>
-          <forkMode>always</forkMode> <!-- required to correctly run the PojoServer tests -->
-          <useSystemClassLoader>true</useSystemClassLoader>
-          <redirectTestOutputToFile>true</redirectTestOutputToFile>
-          <testFailureIgnore>true</testFailureIgnore>
-        </configuration>
-      </plugin>
-      <plugin>
-         <groupId>org.apache.maven.plugins</groupId>
-         <artifactId>maven-release-plugin</artifactId>
-         <version>2.0-beta-7</version>
-         <configuration>
-           <tagBase>https://svn.jboss.org/repos/jbossas/projects/vfs/tags</tagBase>
-         </configuration>
-       </plugin>
-    </plugins>
-  </build>
-
-  <dependencies>
-    <dependency>
-      <groupId>org.jboss</groupId>
-      <artifactId>jboss-common-core</artifactId>
-      <version>${version.jboss.common.core}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jboss.logging</groupId>
-      <artifactId>jboss-logging-spi</artifactId>
-      <version>${version.jboss.logging}</version>
-    </dependency>
-    <dependency>
-      <groupId>org.jboss.test</groupId>
-      <artifactId>jboss-test</artifactId>
-      <version>${version.jboss.test}</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>${version.junit}</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-</project>

Copied: projects/vfs/tags/2.0.0.GA/pom.xml (from rev 81473, projects/vfs/branches/Branch_2_0/pom.xml)
===================================================================
--- projects/vfs/tags/2.0.0.GA/pom.xml	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/pom.xml	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,122 @@
+<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.jboss</groupId>
+    <artifactId>jboss-parent</artifactId>
+    <version>4</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.jboss</groupId>
+  <artifactId>jboss-vfs</artifactId>
+  <packaging>jar</packaging>
+  <version>2.0.0.GA</version>
+  <name>JBoss VFS</name>
+  <url>http://www.jboss.org</url>
+  <description>A VFS library</description>
+ <scm>
+    <connection>scm:svn:http://anonsvn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.GA</connection>    
+    <developerConnection>scm:svn:https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.GA</developerConnection>
+    <url>https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.GA</url>
+  </scm>
+  <licenses>
+    <license>
+      <name>lgpl</name>
+      <url>http://repository.jboss.org/licenses/lgpl.txt</url>
+    </license>
+  </licenses>
+  <organization>
+    <name>JBoss, A division of Red Hat, Inc</name>
+    <url>http://www.jboss.org</url>
+  </organization>
+
+  <properties>
+    <version.jboss.common.core>2.2.9.GA</version.jboss.common.core>
+    <version.jboss.logging>2.0.5.GA</version.jboss.logging>
+    <version.jboss.test>1.1.0.GA</version.jboss.test>
+    <version.junit>4.4</version.junit>
+  </properties>
+
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <testSourceDirectory>src/test/java</testSourceDirectory>
+    <finalName>${artifactId}</finalName>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+      </testResource>
+    </testResources>
+    <plugins>
+      
+      <!-- define how we want compilation to take place
+        here, we accept most of the defaults but say that we want the
+        optimization flag set, and define the source and target to be 1.5,
+        these setting will be inherited by child projects -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.0</version>
+        <configuration>
+          <debug>true</debug>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <!-- define that we wish to create src jars -->
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+        <inherited>true</inherited>
+        <executions>
+          <execution>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.3.1</version>
+        <configuration>
+          <forkMode>always</forkMode> <!-- required to correctly run the PojoServer tests -->
+          <useSystemClassLoader>true</useSystemClassLoader>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+          <testFailureIgnore>true</testFailureIgnore>
+        </configuration>
+      </plugin>
+      <plugin>
+         <groupId>org.apache.maven.plugins</groupId>
+         <artifactId>maven-release-plugin</artifactId>
+         <version>2.0-beta-7</version>
+         <configuration>
+           <tagBase>https://svn.jboss.org/repos/jbossas/projects/vfs/tags</tagBase>
+         </configuration>
+       </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.jboss</groupId>
+      <artifactId>jboss-common-core</artifactId>
+      <version>${version.jboss.common.core}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.logging</groupId>
+      <artifactId>jboss-logging-spi</artifactId>
+      <version>${version.jboss.logging}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.test</groupId>
+      <artifactId>jboss-test</artifactId>
+      <version>${version.jboss.test}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>${version.junit}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/VFS.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,399 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.util.List;
-
-import org.jboss.virtual.plugins.vfs.helpers.WrappingVirtualFileHandlerVisitor;
-import org.jboss.virtual.plugins.context.VfsArchiveBrowserFactory;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VFSContextFactory;
-import org.jboss.virtual.spi.VFSContextFactoryLocator;
-import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.virtual.spi.cache.VFSCacheFactory;
-import org.jboss.virtual.spi.cache.VFSCache;
-import org.jboss.util.file.ArchiveBrowser;
-
-/**
- * Virtual File System
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author Scott.Stark at jboss.org
- * @author <a href="ales.justin at jboss.com">Ales Justin</a> 
- * @version $Revision: 1.1 $
- */
-public class VFS
-{
-   /** The VFS Context */
-   private final VFSContext context;
-
-   static
-   {
-      init();
-   }
-
-   /**
-    * Initialize VFS protocol handlers package property. 
-    */
-   public static void init()
-   {
-      String pkgs = System.getProperty("java.protocol.handler.pkgs");
-      if (pkgs == null || pkgs.trim().length() == 0)
-      {
-         pkgs = "org.jboss.virtual.protocol";
-         System.setProperty("java.protocol.handler.pkgs", pkgs);
-      }
-      else if (!pkgs.contains("org.jboss.virtual.protocol"))
-      {
-         pkgs += "|org.jboss.virtual.protocol";
-         System.setProperty("java.protocol.handler.pkgs", pkgs);
-      }
-      // keep this until AOP and HEM uses VFS internally instead of the stupid ArchiveBrowser crap.
-      ArchiveBrowser.factoryFinder.put("vfsfile", new VfsArchiveBrowserFactory());
-      ArchiveBrowser.factoryFinder.put("vfsjar", new VfsArchiveBrowserFactory());
-      ArchiveBrowser.factoryFinder.put("vfs", new VfsArchiveBrowserFactory());      
-   }
-
-   /**
-    * Get the virtual file system for a root uri
-    * 
-    * @param rootURI the root URI
-    * @return the virtual file system
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL is null
-    */
-   public static VFS getVFS(URI rootURI) throws IOException
-   {
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURI);
-      if (factory == null)
-         throw new IOException("No context factory for " + rootURI);
-      VFSContext context = factory.getVFS(rootURI);
-      VFSCacheFactory.getInstance().putContext(context);
-      return context.getVFS();
-   }
-
-   /**
-    * Get the root virtual file
-    * 
-    * @param rootURI the root uri
-    * @return the virtual file
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL is null
-    */
-   public static VirtualFile getRoot(URI rootURI) throws IOException
-   {
-      VFS vfs = getVFS(rootURI);
-      return vfs.getRoot();
-   }
-
-   /**
-    * Get cached file.
-    *
-    * If VFSContext matching the rootURI parameter is cached
-    * this method will return cached virtual file
-    * else it will use VFS::getRoot(rootURI).
-    *
-    * @param rootURI the root uri
-    * @return the cached virtual file
-    * @throws IOException for any error
-    * @throws IllegalArgumentException if the rootURL is null
-    */
-   public static VirtualFile getCachedFile(URI rootURI) throws IOException
-   {
-      VFSCache cache = VFSCacheFactory.getInstance();
-      return cache.getFile(rootURI);
-   }
-
-   /**
-    * Get a virtual file
-    * 
-    * @param rootURI the root uri
-    * @param name the path name
-    * @return the virtual file
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL or name is null
-    */
-   public static VirtualFile getVirtualFile(URI rootURI, String name) throws IOException
-   {
-      VFS vfs = getVFS(rootURI);
-      return vfs.findChild(name);
-   }
-
-   /**
-    * Get the virtual file system for a root url
-    * 
-    * @param rootURL the root url
-    * @return the virtual file system
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL is null
-    */
-   public static VFS getVFS(URL rootURL) throws IOException
-   {
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURL);
-      if (factory == null)
-         throw new IOException("No context factory for " + rootURL);
-      VFSContext context = factory.getVFS(rootURL);
-      VFSCacheFactory.getInstance().putContext(context);
-      return context.getVFS();
-   }
-
-   /**
-    * Get the root virtual file
-    * 
-    * @param rootURL the root url
-    * @return the virtual file
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL
-    */
-   public static VirtualFile getRoot(URL rootURL) throws IOException
-   {
-      VFS vfs = getVFS(rootURL);
-      return vfs.getRoot();
-   }
-
-   /**
-    * Get cached file.
-    *
-    * If VFSContext matching the rootURL parameter is cached
-    * this method will return cached virtual file
-    * else it will use VFS::getRoot(rootURL).
-    *
-    * @param rootURL the root url
-    * @return the cached virtual file
-    * @throws IOException for any error
-    * @throws IllegalArgumentException if the rootURL is null
-    */
-   public static VirtualFile getCachedFile(URL rootURL) throws IOException
-   {
-      VFSCache cache = VFSCacheFactory.getInstance();
-      return cache.getFile(rootURL);
-   }
-
-   /**
-    * Get a virtual file
-    * 
-    * @param rootURL the root url
-    * @param name the path name
-    * @return the virtual file
-    * @throws IOException if there is a problem accessing the VFS
-    * @throws IllegalArgumentException if the rootURL or name is null
-    */
-   public static VirtualFile getVirtualFile(URL rootURL, String name) throws IOException
-   {
-      VFS vfs = getVFS(rootURL);
-      return vfs.findChild(name);
-   }
-
-   /**
-    * Create a new VFS.
-    * 
-    * @param context the context
-    * @throws IllegalArgumentException for a null context
-    */
-   public VFS(VFSContext context)
-   {
-      if (context == null)
-         throw new IllegalArgumentException("Null name");
-      this.context = context;
-   }
-   
-   /**
-    * Get the root file of this VFS
-    * 
-    * @return the root
-    * @throws IOException for any problem accessing the VFS
-    */
-   public VirtualFile getRoot() throws IOException
-   {
-      VirtualFileHandler handler = context.getRoot();
-      return handler.getVirtualFile();
-   }
-   
-   /**
-    * Find a child from the root
-    *
-    * @param path the child path
-    * @return the child
-    * @throws IOException for any problem accessing the VFS (including the child does not exist)
-    * @throws IllegalArgumentException if the path is null
-    * @deprecated use getChild, and handle null if not found
-    */
-   @Deprecated
-   public VirtualFile findChild(String path) throws IOException
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-      
-      VirtualFileHandler handler = context.getRoot();
-      VirtualFileHandler result = context.getChild(handler, VFSUtils.fixName(path));
-      if (result == null)
-      {
-         List<VirtualFileHandler> children = handler.getChildren(true);
-         throw new IOException("Child not found " + path + " for " + handler + ", available children: " + children);
-      }
-      return result.getVirtualFile();
-   }
-   
-   /**
-   * Get a child
-   *
-   * @param path the child path
-   * @return the child or <code>null</code> if not found
-   * @throws IOException if a real problem occurs
-   */
-   public VirtualFile getChild(String path) throws IOException
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-
-      VirtualFileHandler handler = context.getRoot();
-      VirtualFileHandler result = context.getChild(handler, VFSUtils.fixName(path));
-      return result != null ? result.getVirtualFile() : null;
-   }
-
-   /**
-    * Find a child from the root
-    * 
-    * @deprecated use {@link #findChild(String)}
-    * @param path the child path
-    * @return the child
-    * @throws IOException for any problem accessing the VFS (including the child does not exist)
-    * @throws IllegalArgumentException if the path is null
-    */
-   @Deprecated
-   public VirtualFile findChildFromRoot(String path) throws IOException
-   {
-      return findChild(path);
-   }
-   
-   /**
-    * Get the children
-    * 
-    * @return the children
-    * @throws IOException for any problem accessing the virtual file system
-    */
-   public List<VirtualFile> getChildren() throws IOException
-   {
-      return getRoot().getChildren(null);
-   }
-
-   /**
-    * Get the children
-    * 
-    * @param filter to filter the children
-    * @return the children
-    * @throws IOException for any problem accessing the virtual file system
-    */
-   public List<VirtualFile> getChildren(VirtualFileFilter filter) throws IOException
-   {
-      return getRoot().getChildren(filter);
-   }
-   
-   /**
-    * Get all the children recursively<p>
-    * 
-    * This always uses {@link VisitorAttributes#RECURSE}
-    * 
-    * @return the children
-    * @throws IOException for any problem accessing the virtual file system
-    */
-   public List<VirtualFile> getChildrenRecursively() throws IOException
-   {
-      return getRoot().getChildrenRecursively(null);
-   }
-   
-   /**
-    * Get all the children recursively<p>
-    * 
-    * This always uses {@link VisitorAttributes#RECURSE}
-    * 
-    * @param filter to filter the children
-    * @return the children
-    * @throws IOException for any problem accessing the virtual file system
-    */
-   public List<VirtualFile> getChildrenRecursively(VirtualFileFilter filter) throws IOException
-   {
-      return getRoot().getChildrenRecursively(filter);
-   }
-   
-   /**
-    * Visit the virtual file system from the root
-    * 
-    * @param visitor the visitor
-    * @throws IOException for any problem accessing the VFS
-    * @throws IllegalArgumentException if the visitor is null
-    */
-   public void visit(VirtualFileVisitor visitor) throws IOException
-   {
-      VirtualFileHandler handler = context.getRoot();
-      if (handler.isLeaf() == false)
-      {
-         WrappingVirtualFileHandlerVisitor wrapper = new WrappingVirtualFileHandlerVisitor(visitor);
-         context.visit(handler, wrapper);
-      }
-   }
-
-   /**
-    * Visit the virtual file system
-    * 
-    * @param file the file
-    * @param visitor the visitor
-    * @throws IOException for any problem accessing the VFS
-    * @throws IllegalArgumentException if the file or visitor is null
-    */
-   protected void visit(VirtualFile file, VirtualFileVisitor visitor) throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-
-      VirtualFileHandler handler = file.getHandler();
-      WrappingVirtualFileHandlerVisitor wrapper = new WrappingVirtualFileHandlerVisitor(visitor);
-      VFSContext handlerContext = handler.getVFSContext();
-      handlerContext.visit(handler, wrapper);
-   }
-
-   @Override
-   public String toString()
-   {
-      return context.toString();
-   }
-
-   @Override
-   public int hashCode()
-   {
-      return context.hashCode();
-   }
-   
-   @Override
-   public boolean equals(Object obj)
-   {
-      if (obj == this)
-         return true;
-      if (obj == null || obj instanceof VFS == false)
-         return false;
-      VFS other = (VFS) obj;
-      return context.equals(other.context);
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/VFS.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFS.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,429 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.List;
+
+import org.jboss.virtual.plugins.vfs.helpers.WrappingVirtualFileHandlerVisitor;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VFSContextFactory;
+import org.jboss.virtual.spi.VFSContextFactoryLocator;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.virtual.spi.ExceptionHandler;
+import org.jboss.virtual.spi.cache.VFSCacheFactory;
+import org.jboss.virtual.spi.cache.VFSCache;
+
+/**
+ * Virtual File System
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a> 
+ * @version $Revision: 1.1 $
+ */
+public class VFS
+{
+   /** The VFS Context */
+   private final VFSContext context;
+
+   static
+   {
+      init();
+   }
+
+   /**
+    * Create a new VFS.
+    *
+    * @param context the context
+    * @throws IllegalArgumentException for a null context
+    */
+   public VFS(VFSContext context)
+   {
+      if (context == null)
+         throw new IllegalArgumentException("Null name");
+      this.context = context;
+   }
+
+   /**
+    * Initialize VFS protocol handlers package property. 
+    */
+   @SuppressWarnings({"deprecation", "unchecked"})
+   public static void init()
+   {
+      String pkgs = System.getProperty("java.protocol.handler.pkgs");
+      if (pkgs == null || pkgs.trim().length() == 0)
+      {
+         pkgs = "org.jboss.virtual.protocol";
+         System.setProperty("java.protocol.handler.pkgs", pkgs);
+      }
+      else if (!pkgs.contains("org.jboss.virtual.protocol"))
+      {
+         pkgs += "|org.jboss.virtual.protocol";
+         System.setProperty("java.protocol.handler.pkgs", pkgs);
+      }
+      org.jboss.virtual.plugins.context.VfsArchiveBrowserFactory factory = org.jboss.virtual.plugins.context.VfsArchiveBrowserFactory.INSTANCE;
+      // keep this until AOP and HEM uses VFS internally instead of the stupid ArchiveBrowser crap.
+      org.jboss.util.file.ArchiveBrowser.factoryFinder.put("vfsfile", factory);
+      org.jboss.util.file.ArchiveBrowser.factoryFinder.put("vfszip", factory);
+      org.jboss.util.file.ArchiveBrowser.factoryFinder.put("vfsjar", factory);
+      org.jboss.util.file.ArchiveBrowser.factoryFinder.put("vfs", factory);
+   }
+
+   /**
+    * Get the vfs context.
+    *
+    * This is package protected method.
+    * Same as VirtualFile::getHandler. 
+    *
+    * @return the vfs context
+    */
+   VFSContext getContext()
+   {
+      return context;
+   }
+
+   /**
+    * Set exception handler.
+    *
+    * @param exceptionHandler the exception handler.
+    */
+   public void setExceptionHandler(ExceptionHandler exceptionHandler)
+   {
+      context.setExceptionHandler(exceptionHandler);
+   }
+
+   /**
+    * Get the virtual file system for a root uri
+    * 
+    * @param rootURI the root URI
+    * @return the virtual file system
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL is null
+    */
+   public static VFS getVFS(URI rootURI) throws IOException
+   {
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURI);
+      if (factory == null)
+         throw new IOException("No context factory for " + rootURI);
+      VFSContext context = factory.getVFS(rootURI);
+      VFSCacheFactory.getInstance().putContext(context);
+      return context.getVFS();
+   }
+
+   /**
+    * Get the root virtual file
+    * 
+    * @param rootURI the root uri
+    * @return the virtual file
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL is null
+    */
+   public static VirtualFile getRoot(URI rootURI) throws IOException
+   {
+      VFS vfs = getVFS(rootURI);
+      return vfs.getRoot();
+   }
+
+   /**
+    * Get cached file.
+    *
+    * If VFSContext matching the rootURI parameter is cached
+    * this method will return cached virtual file
+    * else it will use VFS::getRoot(rootURI).
+    *
+    * @param rootURI the root uri
+    * @return the cached virtual file
+    * @throws IOException for any error
+    * @throws IllegalArgumentException if the rootURL is null
+    */
+   public static VirtualFile getCachedFile(URI rootURI) throws IOException
+   {
+      VFSCache cache = VFSCacheFactory.getInstance();
+      VirtualFile file = cache.getFile(rootURI);
+      return (file != null) ? file : getRoot(rootURI);
+   }
+
+   /**
+    * Get a virtual file
+    * 
+    * @param rootURI the root uri
+    * @param name the path name
+    * @return the virtual file
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL or name is null
+    */
+   @SuppressWarnings("deprecation")
+   public static VirtualFile getVirtualFile(URI rootURI, String name) throws IOException
+   {
+      VFS vfs = getVFS(rootURI);
+      return vfs.findChild(name);
+   }
+
+   /**
+    * Get the virtual file system for a root url
+    * 
+    * @param rootURL the root url
+    * @return the virtual file system
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL is null
+    */
+   public static VFS getVFS(URL rootURL) throws IOException
+   {
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURL);
+      if (factory == null)
+         throw new IOException("No context factory for " + rootURL);
+      VFSContext context = factory.getVFS(rootURL);
+      VFSCacheFactory.getInstance().putContext(context);
+      return context.getVFS();
+   }
+
+   /**
+    * Get the root virtual file
+    * 
+    * @param rootURL the root url
+    * @return the virtual file
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL
+    */
+   public static VirtualFile getRoot(URL rootURL) throws IOException
+   {
+      VFS vfs = getVFS(rootURL);
+      return vfs.getRoot();
+   }
+
+   /**
+    * Get cached file.
+    *
+    * If VFSContext matching the rootURL parameter is cached
+    * this method will return cached virtual file
+    * else it will use VFS::getRoot(rootURL).
+    *
+    * @param rootURL the root url
+    * @return the cached virtual file
+    * @throws IOException for any error
+    * @throws IllegalArgumentException if the rootURL is null
+    */
+   public static VirtualFile getCachedFile(URL rootURL) throws IOException
+   {
+      VFSCache cache = VFSCacheFactory.getInstance();
+      VirtualFile file = cache.getFile(rootURL);
+      return (file != null) ? file : getRoot(rootURL);
+   }
+
+   /**
+    * Get a virtual file
+    * 
+    * @param rootURL the root url
+    * @param name the path name
+    * @return the virtual file
+    * @throws IOException if there is a problem accessing the VFS
+    * @throws IllegalArgumentException if the rootURL or name is null
+    */
+   @SuppressWarnings("deprecation")
+   public static VirtualFile getVirtualFile(URL rootURL, String name) throws IOException
+   {
+      VFS vfs = getVFS(rootURL);
+      return vfs.findChild(name);
+   }
+
+   /**
+    * Get the root file of this VFS
+    * 
+    * @return the root
+    * @throws IOException for any problem accessing the VFS
+    */
+   public VirtualFile getRoot() throws IOException
+   {
+      VirtualFileHandler handler = context.getRoot();
+      return handler.getVirtualFile();
+   }
+   
+   /**
+    * Find a child from the root
+    *
+    * @param path the child path
+    * @return the child
+    * @throws IOException for any problem accessing the VFS (including the child does not exist)
+    * @throws IllegalArgumentException if the path is null
+    * @deprecated use getChild, and handle null if not found
+    */
+   @Deprecated
+   public VirtualFile findChild(String path) throws IOException
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+      
+      VirtualFileHandler handler = context.getRoot();
+      VirtualFileHandler result = context.getChild(handler, VFSUtils.fixName(path));
+      if (result == null)
+      {
+         List<VirtualFileHandler> children = handler.getChildren(true);
+         throw new IOException("Child not found " + path + " for " + handler + ", available children: " + children);
+      }
+      return result.getVirtualFile();
+   }
+   
+   /**
+   * Get a child
+   *
+   * @param path the child path
+   * @return the child or <code>null</code> if not found
+   * @throws IOException if a real problem occurs
+   */
+   public VirtualFile getChild(String path) throws IOException
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+
+      VirtualFileHandler handler = context.getRoot();
+      VirtualFileHandler result = context.getChild(handler, VFSUtils.fixName(path));
+      return result != null ? result.getVirtualFile() : null;
+   }
+
+   /**
+    * Find a child from the root
+    * 
+    * @deprecated use {@link #findChild(String)}
+    * @param path the child path
+    * @return the child
+    * @throws IOException for any problem accessing the VFS (including the child does not exist)
+    * @throws IllegalArgumentException if the path is null
+    */
+   @Deprecated
+   @SuppressWarnings("deprecation")
+   public VirtualFile findChildFromRoot(String path) throws IOException
+   {
+      return findChild(path);
+   }
+   
+   /**
+    * Get the children
+    * 
+    * @return the children
+    * @throws IOException for any problem accessing the virtual file system
+    */
+   public List<VirtualFile> getChildren() throws IOException
+   {
+      return getRoot().getChildren(null);
+   }
+
+   /**
+    * Get the children
+    * 
+    * @param filter to filter the children
+    * @return the children
+    * @throws IOException for any problem accessing the virtual file system
+    */
+   public List<VirtualFile> getChildren(VirtualFileFilter filter) throws IOException
+   {
+      return getRoot().getChildren(filter);
+   }
+   
+   /**
+    * Get all the children recursively<p>
+    * 
+    * This always uses {@link VisitorAttributes#RECURSE}
+    * 
+    * @return the children
+    * @throws IOException for any problem accessing the virtual file system
+    */
+   public List<VirtualFile> getChildrenRecursively() throws IOException
+   {
+      return getRoot().getChildrenRecursively(null);
+   }
+   
+   /**
+    * Get all the children recursively<p>
+    * 
+    * This always uses {@link VisitorAttributes#RECURSE}
+    * 
+    * @param filter to filter the children
+    * @return the children
+    * @throws IOException for any problem accessing the virtual file system
+    */
+   public List<VirtualFile> getChildrenRecursively(VirtualFileFilter filter) throws IOException
+   {
+      return getRoot().getChildrenRecursively(filter);
+   }
+   
+   /**
+    * Visit the virtual file system from the root
+    * 
+    * @param visitor the visitor
+    * @throws IOException for any problem accessing the VFS
+    * @throws IllegalArgumentException if the visitor is null
+    */
+   public void visit(VirtualFileVisitor visitor) throws IOException
+   {
+      VirtualFileHandler handler = context.getRoot();
+      if (handler.isLeaf() == false)
+      {
+         WrappingVirtualFileHandlerVisitor wrapper = new WrappingVirtualFileHandlerVisitor(visitor);
+         context.visit(handler, wrapper);
+      }
+   }
+
+   /**
+    * Visit the virtual file system
+    * 
+    * @param file the file
+    * @param visitor the visitor
+    * @throws IOException for any problem accessing the VFS
+    * @throws IllegalArgumentException if the file or visitor is null
+    */
+   protected void visit(VirtualFile file, VirtualFileVisitor visitor) throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+
+      VirtualFileHandler handler = file.getHandler();
+      WrappingVirtualFileHandlerVisitor wrapper = new WrappingVirtualFileHandlerVisitor(visitor);
+      VFSContext handlerContext = handler.getVFSContext();
+      handlerContext.visit(handler, wrapper);
+   }
+
+   @Override
+   public String toString()
+   {
+      return context.toString();
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return context.hashCode();
+   }
+   
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (obj == this)
+         return true;
+      if (obj == null || obj instanceof VFS == false)
+         return false;
+      VFS other = (VFS) obj;
+      return context.equals(other.context);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/VFSUtils.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,910 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLDecoder;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.jar.Attributes;
-import java.util.jar.JarFile;
-import java.util.jar.Manifest;
-
-import org.jboss.logging.Logger;
-import org.jboss.util.StringPropertyReplacer;
-import org.jboss.util.collection.CollectionsFactory;
-import org.jboss.virtual.plugins.copy.CopyMechanism;
-import org.jboss.virtual.plugins.copy.ExplodedCopyMechanism;
-import org.jboss.virtual.plugins.copy.TempCopyMechanism;
-import org.jboss.virtual.plugins.copy.UnpackCopyMechanism;
-import org.jboss.virtual.spi.LinkInfo;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.virtual.spi.cache.VFSCacheFactory;
-
-/**
- * VFS Utilities
- *
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @version $Revision: 1.1 $
- */
-public class VFSUtils
-{
-   /** The log */
-   private static final Logger log = Logger.getLogger(VFSUtils.class);
-
-   /** The default encoding */
-   private static final String DEFAULT_ENCODING = "UTF-8";
-
-   /** The link */
-   public static final String VFS_LINK_INFIX = ".vfslink";
-
-   /** The link properties */
-   public static final String VFS_LINK_PROPERTIES_SUFFIX = ".vfslink.properties";
-
-   /** The link name */
-   public static final String VFS_LINK_NAME = "vfs.link.name";
-   /** The link target */
-   public static final String VFS_LINK_TARGET = "vfs.link.target";
-
-   /**
-    * The system no force copy key / query
-    */
-   public static final String FORCE_COPY_KEY = "jboss.vfs.forceCopy";
-   public static final String USE_COPY_QUERY = "useCopyJarHandler";
-
-   /**
-    * Key used to force fallback from vfszip (default) to vfsjar
-    */
-   public static final String FORCE_VFS_JAR_KEY = "jboss.vfs.forceVfsJar";
-
-   /**
-    * Key used to turn off reaper mode in vfszip - forcing synchronous (slower) handling of files
-    */
-   public static final String FORCE_NO_REAPER_KEY = "jboss.vfs.forceNoReaper";
-   public static final String NO_REAPER_QUERY = "noReaper";
-
-   /**
-    * Key used to force case sensitive path checking in vfsfile
-    */
-   public static final String FORCE_CASE_SENSITIVE_KEY = "jboss.vfs.forceCaseSensitive";
-   public static final String CASE_SENSITIVE_QUERY = "caseSensitive";
-
-   /**
-    * Key used to turn on memory optimizations - less cache use at the expense of performance
-    */
-   public static final String OPTIMIZE_FOR_MEMORY_KEY = "jboss.vfs.optimizeForMemory";
-
-   /**
-    * Key used to determine VFS Cache impl
-    */
-   public static final String VFS_CACHE_KEY = "jboss.vfs.cache";
-
-   /**
-    * Stop cache.
-    */
-   public static void stopCache()
-   {
-      VFSCacheFactory.getInstance().stop();
-   }
-
-   /**
-    * Get the paths string for a collection of virtual files
-    *
-    * @param paths the paths
-    * @return the string
-    * @throws IllegalArgumentException for null paths
-    */
-   public static String getPathsString(Collection<VirtualFile> paths)
-   {
-      if (paths == null)
-         throw new IllegalArgumentException("Null paths");
-
-      StringBuilder buffer = new StringBuilder();
-      boolean first = true;
-      for (VirtualFile path : paths)
-      {
-         if (path == null)
-            throw new IllegalArgumentException("Null path in " + paths);
-         if (first == false)
-            buffer.append(':');
-         else
-            first = false;
-         buffer.append(path.getPathName());
-      }
-
-      if (first == true)
-         buffer.append("<empty>");
-
-      return buffer.toString();
-   }
-
-   /**
-    * Add manifest paths
-    *
-    * @param file the file
-    * @param paths the paths to add to
-    * @throws IOException if there is an error reading the manifest or the
-    *         virtual file is closed
-    * @throws IllegalStateException if the file has no parent
-    * @throws IllegalArgumentException for a null file or paths
-    */
-   public static void addManifestLocations(VirtualFile file, List<VirtualFile> paths) throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      if (paths == null)
-         throw new IllegalArgumentException("Null paths");
-
-      Manifest manifest = getManifest(file);
-      if (manifest == null)
-         return;
-
-      Attributes mainAttributes = manifest.getMainAttributes();
-      String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
-
-      if (classPath == null)
-      {
-         if (log.isTraceEnabled())
-            log.trace("Manifest has no Class-Path for " + file.getPathName());
-         return;
-      }
-
-      VirtualFile parent = file.getParent();
-      if (parent == null)
-      {
-         log.debug(file + " has no parent.");
-         return;
-      }
-
-      URL parentURL;
-      URL vfsRootURL;
-      int rootPathLength;
-      try
-      {
-         parentURL = parent.toURL();
-         vfsRootURL = file.getVFS().getRoot().toURL();
-         rootPathLength = vfsRootURL.getPath().length();
-      }
-      catch(URISyntaxException e)
-      {
-         log.debug("Failed to get parent URL for " + file + ", reason=" + e);
-         return;
-      }
-
-      String parentPath = parentURL.toString();
-      if(parentPath.endsWith("/") == false)
-         parentPath += "/";
-
-      StringTokenizer tokenizer = new StringTokenizer(classPath);
-      while (tokenizer.hasMoreTokens())
-      {
-         String path = tokenizer.nextToken();
-         try
-         {
-            URL libURL = new URL(parentPath + path);
-            String libPath = libURL.getPath();
-            if(rootPathLength > libPath.length())
-            {
-               log.debug("Invalid rootPath: " + vfsRootURL + ", libPath: " + libPath);
-               continue;
-            }
-
-            String vfsLibPath = libPath.substring(rootPathLength);
-            VirtualFile vf = file.getVFS().getChild(vfsLibPath);
-            if(vf != null)
-            {
-               if(paths.contains(vf) == false)
-               {
-                  paths.add(vf);
-                  // Recursively process the jar
-                  addManifestLocations(vf, paths);
-               }
-            }
-         }
-         catch (IOException e)
-         {
-            log.debug("Manifest Class-Path entry " + path + " ignored for " + file.getPathName() + " reason=" + e);
-         }
-      }
-   }
-
-   /**
-    * Get a manifest from a virtual file,
-    * assuming the virtual file is the root of an archive
-    *
-    * @param archive the root the archive
-    * @return the manifest or null if not found
-    * @throws IOException if there is an error reading the manifest or the
-    *         virtual file is closed
-    * @throws IllegalArgumentException for a null archive
-    */
-   public static Manifest getManifest(VirtualFile archive) throws IOException
-   {
-      if (archive == null)
-         throw new IllegalArgumentException("Null archive");
-
-      VirtualFile manifest = archive.getChild(JarFile.MANIFEST_NAME);
-      if (manifest == null)
-      {
-         if (log.isTraceEnabled())
-            log.trace("Can't find manifest for " + archive.getPathName());
-         return null;
-      }
-      return readManifest(manifest);
-   }
-
-   /**
-    * Read the manifest from given manifest VirtualFile.
-    *
-    * @param manifest the VF to read from
-    * @return JAR's manifest
-    * @throws IOException if problems while opening VF stream occur
-    */
-   public static Manifest readManifest(VirtualFile manifest) throws IOException
-   {
-      if (manifest == null)
-         throw new IllegalArgumentException("Null manifest file");
-
-      InputStream stream = manifest.openStream();
-      try
-      {
-         return new Manifest(stream);
-      }
-      finally
-      {
-         try
-         {
-            stream.close();
-         }
-         catch (IOException ignored)
-         {
-         }
-      }
-   }
-
-   /**
-     * Get a manifest from a virtual file system,
-     * assuming the root of the VFS is the root of an archive
-     *
-     * @param archive the vfs
-     * @return the manifest or null if not found
-     * @throws IOException if there is an error reading the manifest
-     * @throws IllegalArgumentException for a null archive
-     */
-    public static Manifest getManifest(VFS archive) throws IOException
-    {
-       if (archive == null)
-         throw new IllegalArgumentException("Null vfs archive");
-
-       VirtualFile root = archive.getRoot();
-       return getManifest(root);
-    }
-
-   /**
-    * Fix a name (removes any trailing slash)
-    *
-    * @param name the name to fix
-    * @return the fixed name
-    * @throws IllegalArgumentException for a null name
-    */
-   public static String fixName(String name)
-   {
-      if (name == null)
-         throw new IllegalArgumentException("Null name");
-
-      int length = name.length();
-      if (length <= 1)
-         return name;
-      if (name.charAt(length-1) == '/')
-         return name.substring(0, length-1);
-
-      return name;
-   }
-
-   /**
-    * Decode the path with UTF-8 encoding..
-    *
-    * @param path the path to decode
-    * @return decoded path
-    */
-   public static String decode(String path)
-   {
-      return decode(path, DEFAULT_ENCODING);
-   }
-
-   /**
-    * Decode the path.
-    *
-    * @param path the path to decode
-    * @param encoding the encodeing
-    * @return decoded path
-    */
-   public static String decode(String path, String encoding)
-   {
-      try
-      {
-         return URLDecoder.decode(path, encoding);
-      }
-      catch (UnsupportedEncodingException e)
-      {
-         throw new IllegalArgumentException("Cannot decode: " + path + " [" + encoding + "]", e);
-      }
-   }
-
-   /**
-    * Get the name.
-    *
-    * @param uri the uri
-    * @return name from uri's path
-    */
-   public static String getName(URI uri)
-   {
-      if (uri == null)
-         throw new IllegalArgumentException("Null uri");
-
-      String name = uri.getPath();
-      if( name != null )
-      {
-         // TODO: Not correct for certain uris like jar:...!/
-         int lastSlash = name.lastIndexOf('/');
-         if( lastSlash > 0 )
-            name = name.substring(lastSlash+1);
-      }
-      return name;
-   }
-
-   /**
-    * Take a URL.getQuery string and parse it into name=value pairs
-    *
-    * @param query Possibly empty/null url query string
-    * @return String[] for the name/value pairs in the query. May be empty but never null.
-    */
-   public static Map<String, String> parseURLQuery(String query)
-   {
-	   Map<String, String> pairsMap = CollectionsFactory.createLazyMap();
-      if(query != null)
-      {
-   	   StringTokenizer tokenizer = new StringTokenizer(query, "=&");
-   	   while(tokenizer.hasMoreTokens())
-   	   {
-   		   String name = tokenizer.nextToken();
-   		   String value = tokenizer.nextToken();
-   		   pairsMap.put(name, value);
-   	   }
-      }
-	   return pairsMap;
-   }
-
-   /**
-    * Does a vf name contain the VFS link prefix
-    * @param name - the name portion of a virtual file
-    * @return true if the name starts with VFS_LINK_PREFIX, false otherwise
-    */
-   public static boolean isLink(String name)
-   {
-      if (name == null)
-         throw new IllegalArgumentException("Null name");
-
-      return name.indexOf(VFS_LINK_INFIX) >= 0;
-   }
-
-   /**
-    * Read the link information from the stream based on the type as determined
-    * from the name suffix.
-    *
-    * @param is - input stream to the link file contents
-    * @param name - the name of the virtual file representing the link
-    * @param props the propertes
-    * @return a list of the links read from the stream
-    * @throws IOException on failure to read/parse the stream
-    * @throws URISyntaxException for an error parsing a URI
-    */
-   public static List<LinkInfo> readLinkInfo(InputStream is, String name, Properties props)
-      throws IOException, URISyntaxException
-   {
-      if (name == null)
-         throw new IllegalArgumentException("Null name");
-
-      if(name.endsWith(VFS_LINK_PROPERTIES_SUFFIX))
-      {
-         List<LinkInfo> info = new ArrayList<LinkInfo>();
-         parseLinkProperties(is, info, props);
-         return info;
-      }
-      else
-         throw new UnsupportedEncodingException("Unknown link format: " + name);
-   }
-
-   /**
-    * Parse a properties link file
-    *
-    * @param is - input stream to the link file contents
-    * @param info the link infos
-    * @param props the propertes
-    * @throws IOException on failure to read/parse the stream
-    * @throws URISyntaxException for an error parsing a URI
-    */
-   public static void parseLinkProperties(InputStream is, List<LinkInfo> info, Properties props)
-      throws IOException, URISyntaxException
-   {
-      if (is == null)
-         throw new IllegalArgumentException("Null input stream");
-      if (info == null)
-         throw new IllegalArgumentException("Null info");
-      if (props == null)
-         throw new IllegalArgumentException("Null properties");
-
-      props.load(is);
-      // Iterate over the property tuples
-      for(int n = 0; ; n ++)
-      {
-         String nameKey = VFS_LINK_NAME + "." + n;
-         String name = props.getProperty(nameKey);
-         String uriKey = VFS_LINK_TARGET + "." + n;
-         String uri = props.getProperty(uriKey);
-         // End when the value is null since a link may not have a name
-         if (uri == null)
-         {
-            break;
-         }
-         // Replace any system property references
-         uri = StringPropertyReplacer.replaceProperties(uri);
-         LinkInfo link = new LinkInfo(name, new URI(uri));
-         info.add(link);
-      }
-   }
-
-   /**
-    * Deal with urls that may include spaces.
-    *
-    * @param url the url
-    * @return uri the uri
-    * @throws URISyntaxException for any error
-    */
-   public static URI toURI(URL url) throws URISyntaxException
-   {
-      if (url == null)
-         throw new IllegalArgumentException("Null url");
-
-      try
-      {
-         return url.toURI();
-      }
-      catch (URISyntaxException e)
-      {
-         String urispec = url.toExternalForm();
-         // Escape percent sign and spaces
-         urispec = urispec.replaceAll("%", "%25");
-         urispec = urispec.replaceAll(" ", "%20");
-         return new URI(urispec);
-      }
-   }
-
-   /**
-    * Ensure the url is convertible to URI by encoding spaces and percent characters if necessary
-    *
-    * @param url to be sanitized
-    * @return sanitized URL
-    * @throws URISyntaxException if URI conversion can't be fixed
-    * @throws MalformedURLException if an error occurs
-    */
-   public static URL sanitizeURL(URL url) throws URISyntaxException, MalformedURLException
-   {
-      return toURI(url).toURL();
-   }
-
-   /**
-    * Get the options for this file.
-    *
-    * @param file the file
-    * @return options map
-    */
-   private static Map<String, String> getOptions(VirtualFile file)
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-
-      VirtualFileHandler handler = file.getHandler();
-      VFSContext context = handler.getVFSContext();
-      return context.getOptions();
-   }
-
-   /**
-    * Get the option.
-    *
-    * @param file the file
-    * @param key the option key
-    * @return key's option
-    */
-   public static String getOption(VirtualFile file, String key)
-   {
-      Map<String, String> options = getOptions(file);
-      return options != null ? options.get(key) : null;
-   }
-
-   /**
-    * Enable option.
-    *
-    * @param file the file
-    * @param optionName option name
-    */
-   protected static void enableOption(VirtualFile file, String optionName)
-   {
-      Map<String, String> options = getOptions(file);
-      if (options == null)
-         throw new IllegalArgumentException("Cannot enable " + optionName + " on null options: " + file);
-
-      options.put(optionName, Boolean.TRUE.toString());
-   }
-
-   /**
-    * Disable option.
-    *
-    * @param file the file
-    * @param optionName option name
-    */
-   protected static void disableOption(VirtualFile file, String optionName)
-   {
-      Map<String, String> options = getOptions(file);
-      if (options == null)
-         throw new IllegalArgumentException("Cannot disable " + optionName + " on null options: " + file);
-
-      options.remove(optionName);
-   }
-
-   /**
-    * Enable copy for file param.
-    *
-    * @param file the file
-    */
-   public static void enableCopy(VirtualFile file)
-   {
-      enableOption(file, USE_COPY_QUERY);
-   }
-
-   /**
-    * Disable copy for file param.
-    *
-    * @param file the file
-    */
-   public static void disableCopy(VirtualFile file)
-   {
-      disableOption(file, USE_COPY_QUERY);
-   }
-
-   /**
-    * Enable repaer for file param.
-    *
-    * @param file the file
-    */
-   public static void enableNoReaper(VirtualFile file)
-   {
-      enableOption(file, NO_REAPER_QUERY);
-   }
-
-   /**
-    * Disable reaper for file param.
-    *
-    * @param file the file
-    */
-   public static void disableNoReaper(VirtualFile file)
-   {
-      disableOption(file, NO_REAPER_QUERY);
-   }
-
-   /**
-    * Enable case sensitive for file param.
-    *
-    * @param file the file
-    */
-   public static void enableCaseSensitive(VirtualFile file)
-   {
-      enableOption(file, CASE_SENSITIVE_QUERY);
-   }
-
-   /**
-    * Disable case sensitive for file param.
-    *
-    * @param file the file
-    */
-   public static void disableCaseSensitive(VirtualFile file)
-   {
-      disableOption(file, CASE_SENSITIVE_QUERY);
-   }
-
-   /**
-    * Unpack the nested artifact under file param.
-    *
-    * @param file the file to unpack
-    * @return unpacked file
-    * @throws IOException for any io error
-    * @throws URISyntaxException for any uri error
-    */
-   public static VirtualFile unpack(VirtualFile file) throws IOException, URISyntaxException
-   {
-      return copy(file, UnpackCopyMechanism.INSTANCE);
-   }
-
-   /**
-    * Force explode.
-    * Explode archives or nested entries.
-    *
-    * @param file the file to explode
-    * @return exploded file
-    * @throws IOException for any io error
-    * @throws URISyntaxException for any uri error
-    */
-   public static VirtualFile explode(VirtualFile file) throws IOException, URISyntaxException
-   {
-      return copy(file, ExplodedCopyMechanism.INSTANCE);
-   }
-
-   /**
-    * Create temp.
-    *
-    * @param file the file to temp
-    * @return temp file
-    * @throws IOException for any io error
-    * @throws URISyntaxException for any uri error
-    */
-   public static VirtualFile temp(VirtualFile file) throws IOException, URISyntaxException
-   {
-      return copy(file, TempCopyMechanism.INSTANCE);
-   }
-
-   /**
-    * Create temp.
-    *
-    * @param file the file to unpack/explode
-    * @param mechanism the copy mechanism
-    * @return temp file
-    * @throws IOException for any io error
-    * @throws URISyntaxException for any uri error
-    */
-   protected static VirtualFile copy(VirtualFile file, CopyMechanism mechanism) throws IOException, URISyntaxException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      if (mechanism == null)
-         throw new IllegalArgumentException("Null copy mechanism");
-
-      return mechanism.copy(file, file.getHandler());
-   }
-
-   /**
-    * Is file handle nested.
-    *
-    * @param file the file handle to check
-    * @return true if file/dir is nested otherwise false
-    * @throws IOException for any error
-    */
-   public static boolean isNestedFile(VirtualFile file) throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-
-      VirtualFileHandler handler = file.getHandler();
-      return handler.isNested();
-   }
-
-   /**
-    * Copy input stream to output stream and close them both
-    *
-    * @param is input stream
-    * @param os output stream
-    * @throws IOException for any error
-    */
-   public static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException
-   {
-      try
-      {
-         copyStream(is, os);
-      }
-      finally
-      {
-         if (is != null)
-         {
-            try
-            {
-               is.close();
-            }
-            catch(IOException ignored)
-            {
-            }
-         }
-         if (os != null)
-            os.close();
-      }
-   }
-
-   /**
-    * Copy input stream to output stream without closing streams.
-    * Flushes output stream when done.
-    *
-    * @param is input stream
-    * @param os output stream
-    * @throws IOException for any error
-    */
-   public static void copyStream(InputStream is, OutputStream os) throws IOException
-   {
-      if (is == null)
-         throw new IllegalArgumentException("input stream is null");
-      if (os == null)
-         throw new IllegalArgumentException("output stream is null");
-
-      try
-      {
-         byte [] buff = new byte[65536];
-         int rc = is.read(buff);
-         while (rc != -1)
-         {
-            os.write(buff, 0, rc);
-            rc = is.read(buff);
-         }
-      }
-      finally
-      {
-         os.flush();
-      }
-   }
-
-   /**
-    * Get spec compatilbe url from virtual file.
-    *
-    * @param file the virtual file
-    * @return spec compatible url
-    * @throws Exception for any error
-    */
-   public static URL getCompatibleURL(VirtualFile file) throws Exception
-   {
-      return getCompatibleResource(file, URL_CREATOR);
-   }
-
-   /**
-    * Get spec compatilbe uri from virtual file.
-    *
-    * @param file the virtual file
-    * @return spec compatible uri
-    * @throws Exception for any error
-    */
-   public static URI getCompatibleURI(VirtualFile file) throws Exception
-   {
-      return getCompatibleResource(file, URI_CREATOR);
-   }
-
-   /**
-    * Create new compatible resource.
-    *
-    * @param file the virtual file
-    * @param creator resoruce creator
-    * @return new resource
-    * @throws Exception for any error
-    * @param <T> exact resource type
-    */
-   private static <T> T getCompatibleResource(VirtualFile file, ResourceCreator<T> creator) throws Exception
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      if (creator == null)
-         throw new IllegalArgumentException("Null creator");
-
-      T resource = creator.getResource(file);
-      if (resource == null)
-         throw new IllegalArgumentException("Null resource: " + file);
-
-      // is not nested, so direct VFS resource is not an option
-      if (isNestedFile(file) == false)
-      {
-         String uriString = creator.getString(resource);
-         if (uriString.startsWith("vfs"))
-         {
-            // treat vfszip as file
-            if (uriString.startsWith("vfszip"))
-               resource = creator.createResource("file" + uriString.substring(6));
-            else
-               resource = creator.createResource(uriString.substring(3)); // (vfs)file and (vfs)jar are ok
-         }
-      }
-      return resource;
-   }
-
-   /**
-    * @param <T> exact resource type
-    */
-   private static interface ResourceCreator<T>
-   {
-      /**
-       * Get resource from virtual file.
-       *
-       * @param file the virtual file
-       * @return resource instance from file
-       * @throws Exception for any error
-       */
-      T getResource(VirtualFile file) throws Exception;
-
-      /**
-       * Get string from resource.
-       *
-       * @param resource the resource
-       * @return resoruce's string representation
-       */
-      String getString(T resource);
-
-      /**
-       * Create new resource.
-       *
-       * @param string the string to create resource from
-       * @return new resoruce instance
-       * @throws Exception for any error
-       */
-      T createResource(String string) throws Exception;
-   }
-
-   private static final ResourceCreator<URL> URL_CREATOR = new ResourceCreator<URL>()
-   {
-      public URL getResource(VirtualFile file) throws Exception
-      {
-         return file.toURL();
-      }
-
-      public String getString(URL resource)
-      {
-         return resource.toExternalForm();
-      }
-
-      public URL createResource(String string) throws Exception
-      {
-         return new URL(string);
-      }
-   };
-
-   private static final ResourceCreator<URI> URI_CREATOR = new ResourceCreator<URI>()
-   {
-      public URI getResource(VirtualFile file) throws Exception
-      {
-         return file.toURI();
-      }
-
-      public String getString(URI resource)
-      {
-         return resource.toString();
-      }
-
-      public URI createResource(String string) throws Exception
-      {
-         return new URI(string);
-      }
-   };
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/VFSUtils.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/VFSUtils.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,1051 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.jboss.logging.Logger;
+import org.jboss.util.StringPropertyReplacer;
+import org.jboss.util.collection.CollectionsFactory;
+import org.jboss.virtual.plugins.copy.CopyMechanism;
+import org.jboss.virtual.plugins.copy.ExplodedCopyMechanism;
+import org.jboss.virtual.plugins.copy.TempCopyMechanism;
+import org.jboss.virtual.plugins.copy.UnpackCopyMechanism;
+import org.jboss.virtual.spi.LinkInfo;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.virtual.spi.cache.VFSCacheFactory;
+
+/**
+ * VFS Utilities
+ *
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 1.1 $
+ */
+public class VFSUtils
+{
+   /** The log */
+   private static final Logger log = Logger.getLogger(VFSUtils.class);
+
+   /** The default encoding */
+   private static final String DEFAULT_ENCODING = "UTF-8";
+
+   /** The link */
+   public static final String VFS_LINK_INFIX = ".vfslink";
+
+   /** The link properties */
+   public static final String VFS_LINK_PROPERTIES_SUFFIX = ".vfslink.properties";
+
+   /** The link name */
+   public static final String VFS_LINK_NAME = "vfs.link.name";
+   /** The link target */
+   public static final String VFS_LINK_TARGET = "vfs.link.target";
+
+   /**
+    * The system no force copy key / query
+    */
+   public static final String FORCE_COPY_KEY = "jboss.vfs.forceCopy";
+   public static final String USE_COPY_QUERY = "useCopyJarHandler";
+
+   /**
+    * Key used to force fallback from vfszip (default) to vfsjar
+    */
+   public static final String FORCE_VFS_JAR_KEY = "jboss.vfs.forceVfsJar";
+
+   /**
+    * Key used to turn off reaper mode in vfszip - forcing synchronous (slower) handling of files
+    */
+   public static final String FORCE_NO_REAPER_KEY = "jboss.vfs.forceNoReaper";
+   public static final String NO_REAPER_QUERY = "noReaper";
+
+   /**
+    * Key used to force case sensitive path checking in vfsfile
+    */
+   public static final String FORCE_CASE_SENSITIVE_KEY = "jboss.vfs.forceCaseSensitive";
+   public static final String CASE_SENSITIVE_QUERY = "caseSensitive";
+
+   /**
+    * Key used to turn on memory optimizations - less cache use at the expense of performance
+    */
+   public static final String OPTIMIZE_FOR_MEMORY_KEY = "jboss.vfs.optimizeForMemory";
+
+   /**
+    * Key used to determine VFS Cache impl
+    */
+   public static final String VFS_CACHE_KEY = "jboss.vfs.cache";
+
+   /**
+    * Constant representing the URL file protocol
+    */
+   public static final String FILE_PROTOCOL = "file";
+   
+   /** Standard separator for JAR URL */
+   public static final String JAR_URL_SEPARATOR = "!/";
+   
+   /**
+    * Stop cache.
+    */
+   public static void stopCache()
+   {
+      VFSCacheFactory.getInstance().stop();
+   }
+
+   /**
+    * Get the paths string for a collection of virtual files
+    *
+    * @param paths the paths
+    * @return the string
+    * @throws IllegalArgumentException for null paths
+    */
+   public static String getPathsString(Collection<VirtualFile> paths)
+   {
+      if (paths == null)
+         throw new IllegalArgumentException("Null paths");
+
+      StringBuilder buffer = new StringBuilder();
+      boolean first = true;
+      for (VirtualFile path : paths)
+      {
+         if (path == null)
+            throw new IllegalArgumentException("Null path in " + paths);
+         if (first == false)
+            buffer.append(':');
+         else
+            first = false;
+         buffer.append(path.getPathName());
+      }
+
+      if (first == true)
+         buffer.append("<empty>");
+
+      return buffer.toString();
+   }
+
+   /**
+    * Add manifest paths
+    *
+    * @param file the file
+    * @param paths the paths to add to
+    * @throws IOException if there is an error reading the manifest or the
+    *         virtual file is closed
+    * @throws IllegalStateException if the file has no parent
+    * @throws IllegalArgumentException for a null file or paths
+    */
+   public static void addManifestLocations(VirtualFile file, List<VirtualFile> paths) throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      if (paths == null)
+         throw new IllegalArgumentException("Null paths");
+
+      Manifest manifest = getManifest(file);
+      if (manifest == null)
+         return;
+
+      Attributes mainAttributes = manifest.getMainAttributes();
+      String classPath = mainAttributes.getValue(Attributes.Name.CLASS_PATH);
+
+      if (classPath == null)
+      {
+         if (log.isTraceEnabled())
+            log.trace("Manifest has no Class-Path for " + file.getPathName());
+         return;
+      }
+
+      VirtualFile parent = file.getParent();
+      if (parent == null)
+      {
+         log.debug(file + " has no parent.");
+         return;
+      }
+
+      URL parentURL;
+      URL vfsRootURL;
+      int rootPathLength;
+      try
+      {
+         parentURL = parent.toURL();
+         vfsRootURL = file.getVFS().getRoot().toURL();
+         rootPathLength = vfsRootURL.getPath().length();
+      }
+      catch(URISyntaxException e)
+      {
+         log.debug("Failed to get parent URL for " + file + ", reason=" + e);
+         return;
+      }
+
+      String parentPath = parentURL.toString();
+      if(parentPath.endsWith("/") == false)
+         parentPath += "/";
+
+      StringTokenizer tokenizer = new StringTokenizer(classPath);
+      while (tokenizer.hasMoreTokens())
+      {
+         String path = tokenizer.nextToken();
+         try
+         {
+            URL libURL = new URL(parentPath + path);
+            String libPath = libURL.getPath();
+            if(rootPathLength > libPath.length())
+            {
+               log.debug("Invalid rootPath: " + vfsRootURL + ", libPath: " + libPath);
+               continue;
+            }
+
+            String vfsLibPath = libPath.substring(rootPathLength);
+            VirtualFile vf = file.getVFS().getChild(vfsLibPath);
+            if(vf != null)
+            {
+               if(paths.contains(vf) == false)
+               {
+                  paths.add(vf);
+                  // Recursively process the jar
+                  addManifestLocations(vf, paths);
+               }
+            }
+         }
+         catch (IOException e)
+         {
+            log.debug("Manifest Class-Path entry " + path + " ignored for " + file.getPathName() + " reason=" + e);
+         }
+      }
+   }
+
+   /**
+    * Get a manifest from a virtual file,
+    * assuming the virtual file is the root of an archive
+    *
+    * @param archive the root the archive
+    * @return the manifest or null if not found
+    * @throws IOException if there is an error reading the manifest or the
+    *         virtual file is closed
+    * @throws IllegalArgumentException for a null archive
+    */
+   public static Manifest getManifest(VirtualFile archive) throws IOException
+   {
+      if (archive == null)
+         throw new IllegalArgumentException("Null archive");
+
+      VirtualFile manifest = archive.getChild(JarFile.MANIFEST_NAME);
+      if (manifest == null)
+      {
+         if (log.isTraceEnabled())
+            log.trace("Can't find manifest for " + archive.getPathName());
+         return null;
+      }
+      return readManifest(manifest);
+   }
+
+   /**
+    * Read the manifest from given manifest VirtualFile.
+    *
+    * @param manifest the VF to read from
+    * @return JAR's manifest
+    * @throws IOException if problems while opening VF stream occur
+    */
+   public static Manifest readManifest(VirtualFile manifest) throws IOException
+   {
+      if (manifest == null)
+         throw new IllegalArgumentException("Null manifest file");
+
+      InputStream stream = manifest.openStream();
+      try
+      {
+         return new Manifest(stream);
+      }
+      finally
+      {
+         try
+         {
+            stream.close();
+         }
+         catch (IOException ignored)
+         {
+         }
+      }
+   }
+
+   /**
+     * Get a manifest from a virtual file system,
+     * assuming the root of the VFS is the root of an archive
+     *
+     * @param archive the vfs
+     * @return the manifest or null if not found
+     * @throws IOException if there is an error reading the manifest
+     * @throws IllegalArgumentException for a null archive
+     */
+    public static Manifest getManifest(VFS archive) throws IOException
+    {
+       if (archive == null)
+         throw new IllegalArgumentException("Null vfs archive");
+
+       VirtualFile root = archive.getRoot();
+       return getManifest(root);
+    }
+
+   /**
+    * Fix a name (removes any trailing slash)
+    *
+    * @param name the name to fix
+    * @return the fixed name
+    * @throws IllegalArgumentException for a null name
+    */
+   public static String fixName(String name)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+
+      int length = name.length();
+      if (length <= 1)
+         return name;
+      if (name.charAt(length-1) == '/')
+         return name.substring(0, length-1);
+
+      return name;
+   }
+
+   /**
+    * Decode the path with UTF-8 encoding..
+    *
+    * @param path the path to decode
+    * @return decoded path
+    */
+   public static String decode(String path)
+   {
+      return decode(path, DEFAULT_ENCODING);
+   }
+
+   /**
+    * Decode the path.
+    *
+    * @param path the path to decode
+    * @param encoding the encodeing
+    * @return decoded path
+    */
+   public static String decode(String path, String encoding)
+   {
+      try
+      {
+         return URLDecoder.decode(path, encoding);
+      }
+      catch (UnsupportedEncodingException e)
+      {
+         throw new IllegalArgumentException("Cannot decode: " + path + " [" + encoding + "]", e);
+      }
+   }
+
+   /**
+    * Get the name.
+    *
+    * @param uri the uri
+    * @return name from uri's path
+    */
+   public static String getName(URI uri)
+   {
+      if (uri == null)
+         throw new IllegalArgumentException("Null uri");
+
+      String name = uri.getPath();
+      if( name != null )
+      {
+         // TODO: Not correct for certain uris like jar:...!/
+         int lastSlash = name.lastIndexOf('/');
+         if( lastSlash > 0 )
+            name = name.substring(lastSlash+1);
+      }
+      return name;
+   }
+
+   /**
+    * Take a URL.getQuery string and parse it into name=value pairs
+    *
+    * @param query Possibly empty/null url query string
+    * @return String[] for the name/value pairs in the query. May be empty but never null.
+    */
+   public static Map<String, String> parseURLQuery(String query)
+   {
+	   Map<String, String> pairsMap = CollectionsFactory.createLazyMap();
+      if(query != null)
+      {
+   	   StringTokenizer tokenizer = new StringTokenizer(query, "=&");
+   	   while(tokenizer.hasMoreTokens())
+   	   {
+   		   String name = tokenizer.nextToken();
+   		   String value = tokenizer.nextToken();
+   		   pairsMap.put(name, value);
+   	   }
+      }
+	   return pairsMap;
+   }
+
+   /**
+    * Does a vf name contain the VFS link prefix
+    * @param name - the name portion of a virtual file
+    * @return true if the name starts with VFS_LINK_PREFIX, false otherwise
+    */
+   public static boolean isLink(String name)
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+
+      return name.indexOf(VFS_LINK_INFIX) >= 0;
+   }
+
+   /**
+    * Read the link information from the stream based on the type as determined
+    * from the name suffix.
+    *
+    * @param is - input stream to the link file contents
+    * @param name - the name of the virtual file representing the link
+    * @param props the propertes
+    * @return a list of the links read from the stream
+    * @throws IOException on failure to read/parse the stream
+    * @throws URISyntaxException for an error parsing a URI
+    */
+   public static List<LinkInfo> readLinkInfo(InputStream is, String name, Properties props)
+      throws IOException, URISyntaxException
+   {
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+
+      if(name.endsWith(VFS_LINK_PROPERTIES_SUFFIX))
+      {
+         List<LinkInfo> info = new ArrayList<LinkInfo>();
+         parseLinkProperties(is, info, props);
+         return info;
+      }
+      else
+         throw new UnsupportedEncodingException("Unknown link format: " + name);
+   }
+
+   /**
+    * Parse a properties link file
+    *
+    * @param is - input stream to the link file contents
+    * @param info the link infos
+    * @param props the propertes
+    * @throws IOException on failure to read/parse the stream
+    * @throws URISyntaxException for an error parsing a URI
+    */
+   public static void parseLinkProperties(InputStream is, List<LinkInfo> info, Properties props)
+      throws IOException, URISyntaxException
+   {
+      if (is == null)
+         throw new IllegalArgumentException("Null input stream");
+      if (info == null)
+         throw new IllegalArgumentException("Null info");
+      if (props == null)
+         throw new IllegalArgumentException("Null properties");
+
+      props.load(is);
+      // Iterate over the property tuples
+      for(int n = 0; ; n ++)
+      {
+         String nameKey = VFS_LINK_NAME + "." + n;
+         String name = props.getProperty(nameKey);
+         String uriKey = VFS_LINK_TARGET + "." + n;
+         String uri = props.getProperty(uriKey);
+         // End when the value is null since a link may not have a name
+         if (uri == null)
+         {
+            break;
+         }
+         // Replace any system property references
+         uri = StringPropertyReplacer.replaceProperties(uri);
+         LinkInfo link = new LinkInfo(name, new URI(uri));
+         info.add(link);
+      }
+   }
+
+   /**
+    * Deal with urls that may include spaces.
+    *
+    * @param url the url
+    * @return uri the uri
+    * @throws URISyntaxException for any error
+    */
+   public static URI toURI(URL url) throws URISyntaxException
+   {
+      if (url == null)
+         throw new IllegalArgumentException("Null url");
+
+      try
+      {
+         return url.toURI();
+      }
+      catch (URISyntaxException e)
+      {
+         String urispec = url.toExternalForm();
+         // Escape percent sign and spaces
+         urispec = urispec.replaceAll("%", "%25");
+         urispec = urispec.replaceAll(" ", "%20");
+         return new URI(urispec);
+      }
+   }
+
+   /**
+    * Ensure the url is convertible to URI by encoding spaces and percent characters if necessary
+    *
+    * @param url to be sanitized
+    * @return sanitized URL
+    * @throws URISyntaxException if URI conversion can't be fixed
+    * @throws MalformedURLException if an error occurs
+    */
+   public static URL sanitizeURL(URL url) throws URISyntaxException, MalformedURLException
+   {
+      return toURI(url).toURL();
+   }
+
+   /**
+    * Get the options for this file.
+    *
+    * @param file the file
+    * @return options map
+    */
+   private static Map<String, String> getOptions(VirtualFile file)
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+
+      VirtualFileHandler handler = file.getHandler();
+      VFSContext context = handler.getVFSContext();
+      return context.getOptions();
+   }
+
+   /**
+    * Get the options for this vfs.
+    *
+    * @param vfs the vfs
+    * @return options map
+    */
+   private static Map<String, String> getOptions(VFS vfs)
+   {
+      if (vfs == null)
+         throw new IllegalArgumentException("Null vfs");
+
+      VFSContext context = vfs.getContext();
+      return context.getOptions();
+   }
+
+   /**
+    * Get the option.
+    *
+    * @param file the file
+    * @param key the option key
+    * @return key's option
+    */
+   public static String getOption(VirtualFile file, String key)
+   {
+      Map<String, String> options = getOptions(file);
+      return options != null ? options.get(key) : null;
+   }
+
+   /**
+    * Get the option.
+    *
+    * @param vfs the vfs
+    * @param key the option key
+    * @return key's option
+    */
+   public static String getOption(VFS vfs, String key)
+   {
+      Map<String, String> options = getOptions(vfs);
+      return options != null ? options.get(key) : null;
+   }
+
+   /**
+    * Enable option.
+    *
+    * @param file the file
+    * @param optionName option name
+    */
+   protected static void enableOption(VirtualFile file, String optionName)
+   {
+      Map<String, String> options = getOptions(file);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot enable " + optionName + " on null options: " + file);
+
+      options.put(optionName, Boolean.TRUE.toString());
+   }
+
+   /**
+    * Disable option.
+    *
+    * @param file the file
+    * @param optionName option name
+    */
+   protected static void disableOption(VirtualFile file, String optionName)
+   {
+      Map<String, String> options = getOptions(file);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot disable " + optionName + " on null options: " + file);
+
+      options.remove(optionName);
+   }
+
+   /**
+    * Enable option.
+    *
+    * @param vfs the vfs
+    * @param optionName option name
+    */
+   protected static void enableOption(VFS vfs, String optionName)
+   {
+      Map<String, String> options = getOptions(vfs);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot enable " + optionName + " on null options: " + vfs);
+
+      options.put(optionName, Boolean.TRUE.toString());
+   }
+
+   /**
+    * Disable option.
+    *
+    * @param vfs the vfs
+    * @param optionName option name
+    */
+   protected static void disableOption(VFS vfs, String optionName)
+   {
+      Map<String, String> options = getOptions(vfs);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot disable " + optionName + " on null options: " + vfs);
+
+      options.remove(optionName);
+   }
+
+   /**
+    * Enable copy for file param.
+    *
+    * @param file the file
+    */
+   public static void enableCopy(VirtualFile file)
+   {
+      enableOption(file, USE_COPY_QUERY);
+   }
+
+   /**
+    * Disable copy for file param.
+    *
+    * @param file the file
+    */
+   public static void disableCopy(VirtualFile file)
+   {
+      disableOption(file, USE_COPY_QUERY);
+   }
+
+   /**
+    * Enable copy for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void enableCopy(VFS vfs)
+   {
+      enableOption(vfs, USE_COPY_QUERY);
+   }
+
+   /**
+    * Disable copy for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void disableCopy(VFS vfs)
+   {
+      disableOption(vfs, USE_COPY_QUERY);
+   }
+
+   /**
+    * Enable reaper for file param.
+    *
+    * @param file the file
+    */
+   public static void enableNoReaper(VirtualFile file)
+   {
+      enableOption(file, NO_REAPER_QUERY);
+   }
+
+   /**
+    * Disable reaper for file param.
+    *
+    * @param file the file
+    */
+   public static void disableNoReaper(VirtualFile file)
+   {
+      disableOption(file, NO_REAPER_QUERY);
+   }
+
+   /**
+    * Enable reaper for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void enableNoReaper(VFS vfs)
+   {
+      enableOption(vfs, NO_REAPER_QUERY);
+   }
+
+   /**
+    * Disable reaper for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void disableNoReaper(VFS vfs)
+   {
+      disableOption(vfs, NO_REAPER_QUERY);
+   }
+
+   /**
+    * Enable case sensitive for file param.
+    *
+    * @param file the file
+    */
+   public static void enableCaseSensitive(VirtualFile file)
+   {
+      enableOption(file, CASE_SENSITIVE_QUERY);
+   }
+
+   /**
+    * Disable case sensitive for file param.
+    *
+    * @param file the file
+    */
+   public static void disableCaseSensitive(VirtualFile file)
+   {
+      disableOption(file, CASE_SENSITIVE_QUERY);
+   }
+
+   /**
+    * Enable case sensitive for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void enableCaseSensitive(VFS vfs)
+   {
+      enableOption(vfs, CASE_SENSITIVE_QUERY);
+   }
+
+   /**
+    * Disable case sensitive for vfs param.
+    *
+    * @param vfs the vfs
+    */
+   public static void disableCaseSensitive(VFS vfs)
+   {
+      disableOption(vfs, CASE_SENSITIVE_QUERY);
+   }
+
+   /**
+    * Unpack the nested artifact under file param.
+    *
+    * @param file the file to unpack
+    * @return unpacked file
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   public static VirtualFile unpack(VirtualFile file) throws IOException, URISyntaxException
+   {
+      return copy(file, UnpackCopyMechanism.INSTANCE);
+   }
+
+   /**
+    * Force explode.
+    * Explode archives or nested entries.
+    *
+    * @param file the file to explode
+    * @return exploded file
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   public static VirtualFile explode(VirtualFile file) throws IOException, URISyntaxException
+   {
+      return copy(file, ExplodedCopyMechanism.INSTANCE);
+   }
+
+   /**
+    * Create temp.
+    *
+    * @param file the file to temp
+    * @return temp file
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   public static VirtualFile temp(VirtualFile file) throws IOException, URISyntaxException
+   {
+      return copy(file, TempCopyMechanism.INSTANCE);
+   }
+
+   /**
+    * Create temp.
+    *
+    * @param file the file to unpack/explode
+    * @param mechanism the copy mechanism
+    * @return temp file
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   protected static VirtualFile copy(VirtualFile file, CopyMechanism mechanism) throws IOException, URISyntaxException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      if (mechanism == null)
+         throw new IllegalArgumentException("Null copy mechanism");
+
+      return mechanism.copy(file, file.getHandler());
+   }
+
+   /**
+    * Is file handle nested.
+    *
+    * @param file the file handle to check
+    * @return true if file/dir is nested otherwise false
+    * @throws IOException for any error
+    */
+   public static boolean isNestedFile(VirtualFile file) throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+
+      VirtualFileHandler handler = file.getHandler();
+      return handler.isNested();
+   }
+
+   /**
+    * Copy input stream to output stream and close them both
+    *
+    * @param is input stream
+    * @param os output stream
+    * @throws IOException for any error
+    */
+   public static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException
+   {
+      try
+      {
+         copyStream(is, os);
+      }
+      finally
+      {
+         if (is != null)
+         {
+            try
+            {
+               is.close();
+            }
+            catch(IOException ignored)
+            {
+            }
+         }
+         if (os != null)
+            os.close();
+      }
+   }
+
+   /**
+    * Copy input stream to output stream without closing streams.
+    * Flushes output stream when done.
+    *
+    * @param is input stream
+    * @param os output stream
+    * @throws IOException for any error
+    */
+   public static void copyStream(InputStream is, OutputStream os) throws IOException
+   {
+      if (is == null)
+         throw new IllegalArgumentException("input stream is null");
+      if (os == null)
+         throw new IllegalArgumentException("output stream is null");
+
+      try
+      {
+         byte [] buff = new byte[65536];
+         int rc = is.read(buff);
+         while (rc != -1)
+         {
+            os.write(buff, 0, rc);
+            rc = is.read(buff);
+         }
+      }
+      finally
+      {
+         os.flush();
+      }
+   }
+
+   /**
+    * Get spec compatilbe url from virtual file.
+    *
+    * @param file the virtual file
+    * @return spec compatible url
+    * @throws Exception for any error
+    */
+   public static URL getCompatibleURL(VirtualFile file) throws Exception
+   {
+      return getCompatibleResource(file, URL_CREATOR);
+   }
+
+   /**
+    * Get spec compatilbe uri from virtual file.
+    *
+    * @param file the virtual file
+    * @return spec compatible uri
+    * @throws Exception for any error
+    */
+   public static URI getCompatibleURI(VirtualFile file) throws Exception
+   {
+      return getCompatibleResource(file, URI_CREATOR);
+   }
+
+   /**
+    * Create new compatible resource.
+    *
+    * @param file the virtual file
+    * @param creator resoruce creator
+    * @return new resource
+    * @throws Exception for any error
+    * @param <T> exact resource type
+    */
+   private static <T> T getCompatibleResource(VirtualFile file, ResourceCreator<T> creator) throws Exception
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      if (creator == null)
+         throw new IllegalArgumentException("Null creator");
+
+      T resource = creator.getResource(file);
+      if (resource == null)
+         throw new IllegalArgumentException("Null resource: " + file);
+
+      // is not nested, so direct VFS resource is not an option
+      if (isNestedFile(file) == false)
+      {
+         String uriString = creator.getString(resource);
+         if (uriString.startsWith("vfs"))
+         {
+            // treat vfszip as file
+            if (uriString.startsWith("vfszip"))
+               resource = creator.createResource("file" + uriString.substring(6));
+            else
+               resource = creator.createResource(uriString.substring(3)); // (vfs)file and (vfs)jar are ok
+         }
+      }
+      return resource;
+   }
+
+   /**
+    * @param <T> exact resource type
+    */
+   private static interface ResourceCreator<T>
+   {
+      /**
+       * Get resource from virtual file.
+       *
+       * @param file the virtual file
+       * @return resource instance from file
+       * @throws Exception for any error
+       */
+      T getResource(VirtualFile file) throws Exception;
+
+      /**
+       * Get string from resource.
+       *
+       * @param resource the resource
+       * @return resoruce's string representation
+       */
+      String getString(T resource);
+
+      /**
+       * Create new resource.
+       *
+       * @param string the string to create resource from
+       * @return new resoruce instance
+       * @throws Exception for any error
+       */
+      T createResource(String string) throws Exception;
+   }
+
+   private static final ResourceCreator<URL> URL_CREATOR = new ResourceCreator<URL>()
+   {
+      public URL getResource(VirtualFile file) throws Exception
+      {
+         return file.toURL();
+      }
+
+      public String getString(URL resource)
+      {
+         return resource.toExternalForm();
+      }
+
+      public URL createResource(String string) throws Exception
+      {
+         return new URL(string);
+      }
+   };
+
+   private static final ResourceCreator<URI> URI_CREATOR = new ResourceCreator<URI>()
+   {
+      public URI getResource(VirtualFile file) throws Exception
+      {
+         return file.toURI();
+      }
+
+      public String getString(URI resource)
+      {
+         return resource.toString();
+      }
+
+      public URI createResource(String string) throws Exception
+      {
+         return new URI(string);
+      }
+   };
+
+   /**
+    * Get real url.
+    * The closest thing that doesn't need the vfs url handlers.
+    *
+    * @param file the virtual file
+    * @return real url
+    * @throws IOException for any error
+    * @throws URISyntaxException for any uri syntac error
+    */
+   public static URL getRealURL(VirtualFile file) throws IOException, URISyntaxException
+   {
+      VirtualFileHandler handler = file.getHandler();
+      return handler.getRealURL();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,256 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.cache;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.virtual.spi.cache.CacheStatistics;
-import org.jboss.virtual.spi.cache.VFSCache;
-
-/**
- * Abstract vfs cache.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class AbstractVFSCache implements VFSCache, CacheStatistics
-{
-   protected Logger log = Logger.getLogger(getClass());
-   
-   private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
-   private long timestamp;
-
-   public long lastInsert()
-   {
-      return timestamp;
-   }
-
-   /**
-    * Is cache valid.
-    */
-   protected abstract void check();
-
-   public VirtualFile getFile(URI uri) throws IOException
-   {
-      check();
-
-      VFSContext context = findContext(uri);
-      if (context != null)
-      {
-         VirtualFileHandler root = context.getRoot();
-         String relativePath = getRelativePath(context, uri);
-         VirtualFileHandler child = root.getChild(relativePath);
-         return child.getVirtualFile();
-      }
-      return VFS.getRoot(uri);
-   }
-
-   /**
-    * Get relative path.
-    *
-    * @param context the vfs context
-    * @param uri the uri
-    * @return uri's relative path to context's root
-    */
-   protected String getRelativePath(VFSContext context, URI uri)
-   {
-      String uriPath = stripProtocol(uri);
-      String contextKey = getKey(context);
-      return uriPath.substring(contextKey.length());
-   }
-
-   public VirtualFile getFile(URL url) throws IOException
-   {
-      check();
-
-      try
-      {
-         return getFile(VFSUtils.toURI(url));
-      }
-      catch (URISyntaxException e)
-      {
-         IOException ioe = new IOException();
-         ioe.initCause(e);
-         throw ioe;
-      }
-   }
-
-   /**
-    * Strip protocol from url string.
-    *
-    * @param uri the uri
-    * @return uri's path string
-    */
-   protected static String stripProtocol(URI uri)
-   {
-      String path = uri.getPath();
-      if (path != null && path.length() > 0)
-      {
-         StringBuilder sb = new StringBuilder(path);
-
-         if (sb.charAt(0) != '/')
-            sb.insert(0, '/');
-         if (sb.charAt(sb.length() - 1) != '/')
-            sb.append('/');
-
-         path = sb.toString();
-      }
-      else
-      {
-         path = "/";
-      }
-
-      return path;
-   }
-
-   /**
-    * Get the cached context.
-    *
-    * @param path the path to match
-    * @return cached context or null if not found
-    */
-   protected abstract VFSContext getContext(String path);
-
-   /**
-    * Find cached context.
-    * This method must take read lock.
-    *
-    * @param uri the uri to match
-    * @return found context or null
-    */
-   protected abstract VFSContext findContext(URI uri);
-
-   /**
-    * Get path key.
-    *
-    * @param context the vfs context
-    * @return contex's root path w/o protocol
-    */
-   protected static String getKey(VFSContext context)
-   {
-      URI uri = context.getRootURI();
-      return stripProtocol(uri);
-   }
-
-   public void putContext(VFSContext context)
-   {
-      if (context == null)
-         throw new IllegalArgumentException("Null context");
-
-      check();
-
-      if (log.isTraceEnabled())
-      {
-         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
-         log.trace("VFSContext: " + context + ", Stack-trace:\n" + Arrays.toString(stackTraceElements));
-      }
-
-      String path = getKey(context);
-      writeLock();
-      try
-      {
-         putContext(path, context);
-         timestamp = System.currentTimeMillis();
-      }
-      finally
-      {
-         writeUnlock();
-      }
-   }
-
-   /**
-    * Put vfs context and its path key into cache.
-    *
-    * @param path the context's path
-    * @param context the vfs context
-    */
-   protected abstract void putContext(String path, VFSContext context);
-
-   public void removeContext(VFSContext context)
-   {
-      if (context == null)
-         throw new IllegalArgumentException("Null context");
-
-      check();
-
-      String path = getKey(context);
-      writeLock();
-      try
-      {
-         removeContext(path, context);
-      }
-      finally
-      {
-         writeUnlock();
-      }
-   }
-
-   /**
-    * Remove vfs context and its path key from cache.
-    *
-    * @param path the context's path
-    * @param context the vfs context
-    */
-   protected abstract void removeContext(String path, VFSContext context);
-
-   /**
-    * Read lock.
-    */
-   protected void readLock()
-   {
-      lock.readLock().lock();
-   }
-
-   /**
-    * Read unlock.
-    */
-   protected void readUnlock()
-   {
-      lock.readLock().unlock();
-   }
-
-   /**
-    * Write lock.
-    */
-   protected void writeLock()
-   {
-      lock.writeLock().lock();
-   }
-
-   /**
-    * Write unlock.
-    */
-   protected void writeUnlock()
-   {
-      lock.writeLock().unlock();
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/AbstractVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,264 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.virtual.spi.cache.CacheStatistics;
+import org.jboss.virtual.spi.cache.VFSCache;
+
+/**
+ * Abstract vfs cache.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class AbstractVFSCache implements VFSCache, CacheStatistics
+{
+   protected Logger log = Logger.getLogger(getClass());
+   
+   private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+   private long timestamp;
+
+   public long lastInsert()
+   {
+      return timestamp;
+   }
+
+   /**
+    * Is cache valid.
+    */
+   protected abstract void check();
+
+   public VirtualFile getFile(URI uri) throws IOException
+   {
+      if (uri == null)
+         throw new IllegalArgumentException("Null uri.");
+
+      check();
+
+      VFSContext context = findContext(uri);
+      if (context != null)
+      {
+         VirtualFileHandler root = context.getRoot();
+         String relativePath = getRelativePath(context, uri);
+         VirtualFileHandler child = root.getChild(relativePath);
+         if (child == null)
+            throw new IOException("Cannot find child, root=" + root + ", relativePath=" + relativePath);
+         
+         return child.getVirtualFile();
+      }
+      return null;
+   }
+
+   /**
+    * Get relative path.
+    *
+    * @param context the vfs context
+    * @param uri the uri
+    * @return uri's relative path to context's root
+    */
+   protected String getRelativePath(VFSContext context, URI uri)
+   {
+      String uriPath = stripProtocol(uri);
+      String contextKey = getKey(context);
+      return uriPath.substring(contextKey.length());
+   }
+
+   public VirtualFile getFile(URL url) throws IOException
+   {
+      if (url == null)
+         throw new IllegalArgumentException("Null url.");
+
+      check();
+
+      try
+      {
+         return getFile(VFSUtils.toURI(url));
+      }
+      catch (URISyntaxException e)
+      {
+         IOException ioe = new IOException();
+         ioe.initCause(e);
+         throw ioe;
+      }
+   }
+
+   /**
+    * Strip protocol from url string.
+    *
+    * @param uri the uri
+    * @return uri's path string
+    */
+   protected static String stripProtocol(URI uri)
+   {
+      String path = uri.getPath();
+      if (path != null && path.length() > 0)
+      {
+         StringBuilder sb = new StringBuilder(path);
+
+         if (sb.charAt(0) != '/')
+            sb.insert(0, '/');
+         if (sb.charAt(sb.length() - 1) != '/')
+            sb.append('/');
+
+         path = sb.toString();
+      }
+      else
+      {
+         path = "/";
+      }
+
+      return path;
+   }
+
+   /**
+    * Get the cached context.
+    *
+    * @param path the path to match
+    * @return cached context or null if not found
+    */
+   protected abstract VFSContext getContext(String path);
+
+   /**
+    * Find cached context.
+    * This method must take read lock.
+    *
+    * @param uri the uri to match
+    * @return found context or null
+    */
+   protected abstract VFSContext findContext(URI uri);
+
+   /**
+    * Get path key.
+    *
+    * @param context the vfs context
+    * @return contex's root path w/o protocol
+    */
+   protected static String getKey(VFSContext context)
+   {
+      URI uri = context.getRootURI();
+      return stripProtocol(uri);
+   }
+
+   public void putContext(VFSContext context)
+   {
+      if (context == null)
+         throw new IllegalArgumentException("Null context");
+
+      check();
+
+      if (log.isTraceEnabled())
+      {
+         StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+         log.trace("VFSContext: " + context + ", Stack-trace:\n" + Arrays.toString(stackTraceElements));
+      }
+
+      String path = getKey(context);
+      writeLock();
+      try
+      {
+         putContext(path, context);
+         timestamp = System.currentTimeMillis();
+      }
+      finally
+      {
+         writeUnlock();
+      }
+   }
+
+   /**
+    * Put vfs context and its path key into cache.
+    *
+    * @param path the context's path
+    * @param context the vfs context
+    */
+   protected abstract void putContext(String path, VFSContext context);
+
+   public void removeContext(VFSContext context)
+   {
+      if (context == null)
+         throw new IllegalArgumentException("Null context");
+
+      check();
+
+      String path = getKey(context);
+      writeLock();
+      try
+      {
+         removeContext(path, context);
+      }
+      finally
+      {
+         writeUnlock();
+      }
+   }
+
+   /**
+    * Remove vfs context and its path key from cache.
+    *
+    * @param path the context's path
+    * @param context the vfs context
+    */
+   protected abstract void removeContext(String path, VFSContext context);
+
+   /**
+    * Read lock.
+    */
+   protected void readLock()
+   {
+      lock.readLock().lock();
+   }
+
+   /**
+    * Read unlock.
+    */
+   protected void readUnlock()
+   {
+      lock.readLock().unlock();
+   }
+
+   /**
+    * Write lock.
+    */
+   protected void writeLock()
+   {
+      lock.writeLock().lock();
+   }
+
+   /**
+    * Write unlock.
+    */
+   protected void writeUnlock()
+   {
+      lock.writeLock().unlock();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,171 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.cache;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collections;
-
-import org.jboss.util.CachePolicy;
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * Cache policy vfs cache.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class CachePolicyVFSCache extends PathMatchingVFSCache
-{
-   private CachePolicy policy;
-
-   public Iterable<VFSContext> getCachedContexts()
-   {
-      // cannot pull all cache entries from policy
-      return Collections.emptySet();
-   }
-
-   public int size()
-   {
-      return policy != null ? policy.size() : -1;
-   }
-
-   protected void check()
-   {
-      if (policy == null)
-         throw new IllegalArgumentException("Cache needs to be started first.");
-   }
-
-   public void start() throws Exception
-   {
-      policy = createCachePolicy();
-      if (policy == null)
-         throw new IllegalArgumentException("Policy is null.");
-
-      policy.create();
-      try
-      {
-         policy.start();
-      }
-      catch (Exception e)
-      {
-         try
-         {
-            policy.destroy();
-         }
-         catch (Exception ignored)
-         {
-         }
-         throw e;
-      }
-   }
-
-   public void stop()
-   {
-      if (policy != null)
-      {
-         try
-         {
-            policy.stop();
-         }
-         catch (Exception ignored)
-         {
-         }
-         try
-         {
-            policy.destroy();
-         }
-         catch (Exception ignored)
-         {
-         }
-         finally
-         {
-            policy = null;
-         }
-      }
-   }
-
-   public void flush()
-   {
-      if (policy != null)
-         policy.flush();
-   }
-
-   protected VFSContext getContext(String path)
-   {
-      return VFSContext.class.cast(policy.get(path));
-   }
-
-   protected void putContext(String path, VFSContext context)
-   {
-      Object result = policy.peek(path);
-      if (result == null)
-         policy.insert(path, context);
-   }
-
-   public void removeContext(String key, VFSContext context)
-   {
-      policy.remove(key);
-   }
-
-   /**
-    * Create cache policy.
-    *
-    * @return the cache policy
-    */
-   protected abstract CachePolicy createCachePolicy();
-
-   /**
-    * Read system property.
-    *
-    * @param key          the property key
-    * @param defaultValue the default value
-    * @return system property or default value
-    */
-   protected static String readSystemProperty(final String key, final String defaultValue)
-   {
-      SecurityManager sm = System.getSecurityManager();
-      if (sm == null)
-         return System.getProperty(key, defaultValue);
-      else
-         return AccessController.doPrivileged(new PrivilegedAction<String>()
-         {
-            public String run()
-            {
-               return System.getProperty(key, defaultValue);
-            }
-         });
-   }
-
-   /**
-    * Parse integer.
-    *
-    * @param value the string int value
-    * @return integer value of null
-    */
-   protected static Integer parseInteger(String value)
-   {
-      if (value == null)
-         return null;
-
-      return Integer.parseInt(value);
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/CachePolicyVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,239 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Map;
+
+import org.jboss.util.CachePolicy;
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * Cache policy vfs cache.
+ *
+ * @param <T> exact policy type
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class CachePolicyVFSCache<T extends CachePolicy> extends PathMatchingVFSCache
+{
+   private T policy;
+   private Map<Object, Object> properties;
+
+   protected CachePolicyVFSCache()
+   {
+   }
+
+   protected CachePolicyVFSCache(Map<Object, Object> properties)
+   {
+      this.properties = properties;
+   }
+
+   public Iterable<VFSContext> getCachedContexts()
+   {
+      // cannot pull all cache entries from policy
+      return Collections.emptySet();
+   }
+
+   public int size()
+   {
+      return policy != null ? policy.size() : -1;
+   }
+
+   /**
+    * Get the policy.
+    * Run check before.
+    *
+    * @return the policy
+    */
+   protected T getPolicy()
+   {
+      check();
+      return policy;
+   }
+
+   protected void check()
+   {
+      if (policy == null)
+         throw new IllegalArgumentException("Cache needs to be started first.");
+   }
+
+   public void start() throws Exception
+   {
+      policy = createCachePolicy();
+      if (policy == null)
+         throw new IllegalArgumentException("Policy is null.");
+
+      policy.create();
+      try
+      {
+         policy.start();
+      }
+      catch (Exception e)
+      {
+         try
+         {
+            policy.destroy();
+         }
+         catch (Exception ignored)
+         {
+         }
+         throw e;
+      }
+   }
+
+   public void stop()
+   {
+      if (policy != null)
+      {
+         try
+         {
+            policy.stop();
+         }
+         catch (Exception ignored)
+         {
+         }
+         try
+         {
+            policy.destroy();
+         }
+         catch (Exception ignored)
+         {
+         }
+         finally
+         {
+            policy = null;
+         }
+      }
+   }
+
+   public void flush()
+   {
+      if (policy != null)
+         policy.flush();
+   }
+
+   protected VFSContext getContext(String path)
+   {
+      return VFSContext.class.cast(policy.get(path));
+   }
+
+   protected void putContext(String path, VFSContext context)
+   {
+      Object result = policy.peek(path);
+      if (result == null)
+         policy.insert(path, context);
+   }
+
+   public void removeContext(String key, VFSContext context)
+   {
+      policy.remove(key);
+   }
+
+   /**
+    * Create cache policy.
+    *
+    * @return the cache policy
+    */
+   protected abstract T createCachePolicy();
+
+   /**
+    * Read instance properties.
+    *
+    * @param key the property key
+    * @param defaultValue the default value
+    * @param useSystemProperties do we fallback to system properties
+    * @return property or default value
+    */
+   protected Object readInstanceProperties(final String key, final Object defaultValue, final boolean useSystemProperties)
+   {
+      Object result = null;
+      if (properties != null && properties.isEmpty() == false)
+      {
+         result = properties.get(key);
+      }
+      if (result == null)
+      {
+         if (useSystemProperties)
+         {
+            String stringDefaultValue = defaultValue != null ? defaultValue.toString() : null;
+            result = readSystemProperty(key, stringDefaultValue);
+         }
+         else
+            result = defaultValue;
+      }
+      return result;
+   }
+
+   /**
+    * Read system property.
+    *
+    * @param key          the property key
+    * @param defaultValue the default value
+    * @return system property or default value
+    */
+   protected static String readSystemProperty(final String key, final String defaultValue)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm == null)
+         return System.getProperty(key, defaultValue);
+      else
+         return AccessController.doPrivileged(new PrivilegedAction<String>()
+         {
+            public String run()
+            {
+               return System.getProperty(key, defaultValue);
+            }
+         });
+   }
+
+   /**
+    * Parse integer.
+    *
+    * @param value the string int value
+    * @return integer value or null
+    */
+   protected static Integer parseInteger(String value)
+   {
+      if (value == null)
+         return null;
+
+      return Integer.parseInt(value);
+   }
+
+   /**
+    * Get integer from value.
+    *
+    * @param value the value
+    * @return integer value or null
+    */
+   protected static Integer getInteger(Object value)
+   {
+      if (value == null)
+         return null;
+      else if (value instanceof Number)
+         return Number.class.cast(value).intValue();
+      else
+         return Integer.parseInt(value.toString());
+   }
+}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/IterableTimedVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/IterableTimedVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/IterableTimedVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/IterableTimedVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,86 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.util.Map;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.net.URI;
+
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.util.TimedCachePolicy;
+
+/**
+ * Iterable timed cache policy vfs cache.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class IterableTimedVFSCache extends TimedVFSCache
+{
+   public IterableTimedVFSCache()
+   {
+   }
+
+   public IterableTimedVFSCache(Integer defaultLifetime)
+   {
+      super(defaultLifetime);
+   }
+
+   public IterableTimedVFSCache(Integer defaultLifetime, Boolean threadSafe, Integer resolution)
+   {
+      super(defaultLifetime, threadSafe, resolution);
+   }
+
+   public IterableTimedVFSCache(Map<Object, Object> properties)
+   {
+      super(properties);
+   }
+
+   @SuppressWarnings("unchecked")
+   protected VFSContext findContext(URI uri)
+   {
+      String uriString = stripProtocol(uri);
+      TimedCachePolicy tcp = getPolicy();
+      List validKeys = tcp.getValidKeys();
+      Set<String> keys = new TreeSet<String>(validKeys);
+      readLock();
+      try
+      {
+         for (String key : keys)
+         {
+            if (uriString.startsWith(key))
+               return getContext(key);
+         }
+      }
+      finally
+      {
+         readUnlock();
+      }
+      return null;
+   }
+
+   protected String getCacheName()
+   {
+      return "Iterable" + super.getCacheName();
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,82 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.cache;
-
-import org.jboss.util.CachePolicy;
-import org.jboss.util.LRUCachePolicy;
-import org.jboss.virtual.VFSUtils;
-
-/**
- * LRU cache policy vfs cache.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class LRUVFSCache extends CachePolicyVFSCache
-{
-   private Integer min;
-   private Integer max;
-
-   public LRUVFSCache()
-   {
-   }
-
-   public LRUVFSCache(Integer min, Integer max)
-   {
-      this.min = min;
-      this.max = max;
-   }
-
-   protected CachePolicy createCachePolicy()
-   {
-      if (min == null)
-         min = parseInteger(readSystemProperty(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.min", null));
-      if (max == null)
-         max = parseInteger(readSystemProperty(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.max", null));
-
-      if (min == null || max == null)
-         throw new IllegalArgumentException("Missing min (" + min + ") or max (" + max + ").");
-
-      log.debug("Creating LRU cache policy, min: " + min + ", max: " + max);
-
-      return new LRUCachePolicy(min, max);
-   }
-
-   /**
-    * Set min.
-    *
-    * @param min the min
-    */
-   public void setMin(Integer min)
-   {
-      this.min = min;
-   }
-
-   /**
-    * set max.
-    *
-    * @param max the max
-    */
-   public void setMax(Integer max)
-   {
-      this.max = max;
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/LRUVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,93 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.util.Map;
+
+import org.jboss.util.LRUCachePolicy;
+import org.jboss.virtual.VFSUtils;
+
+/**
+ * LRU cache policy vfs cache.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class LRUVFSCache extends CachePolicyVFSCache<LRUCachePolicy>
+{
+   private Integer min;
+   private Integer max;
+
+   public LRUVFSCache()
+   {
+   }
+
+   public LRUVFSCache(Integer min, Integer max)
+   {
+      this.min = min;
+      this.max = max;
+   }
+
+   public LRUVFSCache(Map<Object, Object> properties)
+   {
+      super(properties);
+   }
+
+   protected LRUCachePolicy createCachePolicy()
+   {
+      if (min == null)
+         min = getInteger(readInstanceProperties(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.min", null, true));
+      if (max == null)
+         max = getInteger(readInstanceProperties(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.max", null, true));
+
+      if (min == null || max == null)
+         throw new IllegalArgumentException("Missing min (" + min + ") or max (" + max + ").");
+
+      log.debug("Creating LRU cache policy, min: " + min + ", max: " + max);
+
+      return new LRUCachePolicy(min, max);
+   }
+
+   /**
+    * Set min.
+    *
+    * @param min the min
+    */
+   public void setMin(Integer min)
+   {
+      this.min = min;
+   }
+
+   /**
+    * set max.
+    *
+    * @param max the max
+    */
+   public void setMax(Integer max)
+   {
+      this.max = max;
+   }
+
+   public String toString()
+   {
+      return "LRUVFSCache{min=" + min + ", max=" + max + "}";
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,105 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.cache;
-
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFS;
-
-/**
- * Initialize vfs contexts - performance improvements.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class PreInitializeVFSContexts
-{
-   private Logger log = Logger.getLogger(PreInitializeVFSContexts.class);
-   private List<URL> initializedVFSContexts;
-   private boolean holdReference;
-   private List<VFS> references;
-
-   /**
-    * Start initializer.
-    *
-    * @throws Exception for any exception
-    */
-   public void start() throws Exception
-   {
-      if (initializedVFSContexts != null && initializedVFSContexts.isEmpty() == false)
-      {
-         if (holdReference)
-            references = new ArrayList<VFS>();
-
-         for (URL url : initializedVFSContexts)
-         {
-            VFS vfs = VFS.getVFS(url);
-            log.debug("Initialized Virtual File: " + vfs.getRoot());
-            if (holdReference)
-            {
-               references.add(vfs);
-            }
-         }
-      }
-   }
-
-   /**
-    * Clear possible references.
-    */
-   public void stop()
-   {
-      if (references != null)
-         references.clear();
-   }
-
-   /**
-    * Get VFS references.
-    *
-    * @return the VFS references
-    */
-   public List<VFS> getReferences()
-   {
-      return references;
-   }
-
-   /**
-    * Set URLs that need to be initialized before anything else.
-    *
-    * @param initializedVFSContexts the URLs to be initialized
-    */
-   public void setInitializedVFSContexts(List<URL> initializedVFSContexts)
-   {
-      this.initializedVFSContexts = initializedVFSContexts;
-   }
-
-   /**
-    * Should we hold the reference to initialized VFSs.
-    *
-    * @param holdReference the hold reference flag
-    */
-   public void setHoldReference(boolean holdReference)
-   {
-      this.holdReference = holdReference;
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/PreInitializeVFSContexts.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,127 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.spi.ExceptionHandler;
+
+/**
+ * Initialize vfs contexts - performance improvements.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class PreInitializeVFSContexts
+{
+   private Logger log = Logger.getLogger(PreInitializeVFSContexts.class);
+   private Map<URL, ExceptionHandler> initializedVFSContexts;
+   private boolean holdReference;
+   private List<VFS> references;
+
+   /**
+    * Start initializer.
+    *
+    * @throws Exception for any exception
+    */
+   public void start() throws Exception
+   {
+      if (initializedVFSContexts != null && initializedVFSContexts.isEmpty() == false)
+      {
+         if (holdReference)
+            references = new ArrayList<VFS>();
+
+         for (Map.Entry<URL, ExceptionHandler> entry : initializedVFSContexts.entrySet())
+         {
+            VFS vfs = VFS.getVFS(entry.getKey());
+
+            ExceptionHandler eh = entry.getValue();
+            if (eh != null)
+               vfs.setExceptionHandler(eh);
+
+            log.debug("Initialized Virtual File: " + vfs.getRoot());
+            if (holdReference)
+            {
+               references.add(vfs);
+            }
+         }
+      }
+   }
+
+   /**
+    * Clear possible references.
+    */
+   public void stop()
+   {
+      if (references != null)
+         references.clear();
+   }
+
+   /**
+    * Get VFS references.
+    *
+    * @return the VFS references
+    */
+   public List<VFS> getReferences()
+   {
+      return references;
+   }
+
+   /**
+    * Set URLs that need to be initialized before anything else.
+    *
+    * @param initializedVFSContexts the URLs to be initialized
+    */
+   public void setInitializedVFSContexts(List<URL> initializedVFSContexts)
+   {
+      this.initializedVFSContexts = new HashMap<URL, ExceptionHandler>();
+      for (URL url : initializedVFSContexts)
+      {
+         this.initializedVFSContexts.put(url, null);
+      }
+   }
+
+   /**
+    * Set URLs that need to be initialized before anything else.
+    *
+    * @param initializedVFSContexts the URLs to be initialized
+    */
+   public void setInitializedVFSContexts(Map<URL, ExceptionHandler> initializedVFSContexts)
+   {
+      this.initializedVFSContexts = initializedVFSContexts;
+   }
+
+   /**
+    * Should we hold the reference to initialized VFSs.
+    *
+    * @param holdReference the hold reference flag
+    */
+   public void setHoldReference(boolean holdReference)
+   {
+      this.holdReference = holdReference;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,103 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.cache;
-
-import org.jboss.util.CachePolicy;
-import org.jboss.util.TimedCachePolicy;
-import org.jboss.virtual.VFSUtils;
-
-/**
- * Timed cache policy vfs cache.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class TimedVFSCache extends CachePolicyVFSCache
-{
-   private Integer defaultLifetime;
-   private Boolean threadSafe;
-   private Integer resolution;
-
-   public TimedVFSCache()
-   {
-   }
-
-   public TimedVFSCache(Integer defaultLifetime)
-   {
-      this(defaultLifetime, null, null);
-   }
-
-   public TimedVFSCache(Integer defaultLifetime, Boolean threadSafe, Integer resolution)
-   {
-      this.defaultLifetime = defaultLifetime;
-      this.threadSafe = threadSafe;
-      this.resolution = resolution;
-   }
-
-   protected CachePolicy createCachePolicy()
-   {
-      if (defaultLifetime == null)
-         defaultLifetime = parseInteger(readSystemProperty(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.lifetime", null));
-      if (threadSafe == null)
-         threadSafe = Boolean.valueOf(readSystemProperty(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.threadSafe", Boolean.TRUE.toString()));
-      if (resolution == null)
-         resolution = parseInteger(readSystemProperty(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.resolution", null));
-
-      log.debug("Creating timed cache policy, lifetime: " + defaultLifetime + ", threadSafe: " + threadSafe + ", resolution: " + resolution);
-
-      if (defaultLifetime == null)
-         return new TimedCachePolicy();
-      else if (resolution != null)
-         return new TimedCachePolicy(defaultLifetime, threadSafe, resolution);
-      else
-         return new TimedCachePolicy(defaultLifetime);
-   }
-
-   /**
-    * Set default lifetime.
-    *
-    * @param defaultLifetime the default lifetime
-    */
-   public void setDefaultLifetime(Integer defaultLifetime)
-   {
-      this.defaultLifetime = defaultLifetime;
-   }
-
-   /**
-    * Set threadsafe flag.
-    *
-    * @param threadSafe the threadsafe flag
-    */
-   public void setThreadSafe(Boolean threadSafe)
-   {
-      this.threadSafe = threadSafe;
-   }
-
-   /**
-    * The resollution.
-    *
-    * @param resolution the resolution
-    */
-   public void setResolution(Integer resolution)
-   {
-      this.resolution = resolution;
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/cache/TimedVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,152 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.cache;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.jboss.util.TimedCachePolicy;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * Timed cache policy vfs cache.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class TimedVFSCache extends CachePolicyVFSCache<TimedCachePolicy>
+{
+   private Integer defaultLifetime;
+   private Boolean threadSafe;
+   private Integer resolution;
+
+   private String info;
+
+   public TimedVFSCache()
+   {
+   }
+
+   public TimedVFSCache(Integer defaultLifetime)
+   {
+      this(defaultLifetime, null, null);
+   }
+
+   public TimedVFSCache(Integer defaultLifetime, Boolean threadSafe, Integer resolution)
+   {
+      this.defaultLifetime = defaultLifetime;
+      this.threadSafe = threadSafe;
+      this.resolution = resolution;
+   }
+
+   public TimedVFSCache(Map<Object, Object> properties)
+   {
+      super(properties);
+   }
+
+   @Override
+   @SuppressWarnings("unchecked")
+   public Iterable<VFSContext> getCachedContexts()
+   {
+      TimedCachePolicy tcp = getPolicy();
+      List keys = tcp.getValidKeys();
+      if (keys != null && keys.isEmpty() == false)
+      {
+         Map<Object, VFSContext> contexts = new TreeMap<Object, VFSContext>();
+         for (Object key : keys)
+            contexts.put(key, (VFSContext)tcp.peek(key));
+
+         return contexts.values();
+      }
+      return Collections.emptySet();
+   }
+
+   protected TimedCachePolicy createCachePolicy()
+   {
+      if (defaultLifetime == null)
+         defaultLifetime = getInteger(readInstanceProperties(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.lifetime", null, true));
+      if (threadSafe == null)
+         threadSafe = Boolean.valueOf(readInstanceProperties(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.threadSafe", Boolean.TRUE, true).toString());
+      if (resolution == null)
+         resolution = getInteger(readInstanceProperties(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.resolution", null, true));
+
+      log.debug("Creating timed cache policy, lifetime: " + defaultLifetime + ", threadSafe: " + threadSafe + ", resolution: " + resolution);
+
+      TimedCachePolicy tcp;
+      if (defaultLifetime == null)
+         tcp = new TimedCachePolicy();
+      else if (resolution != null)
+         tcp = new TimedCachePolicy(defaultLifetime, threadSafe, resolution);
+      else
+         tcp = new TimedCachePolicy(defaultLifetime);
+
+      info = getCacheName() + "{lifetime=" + tcp.getDefaultLifetime() + ", resolution=" + tcp.getResolution() + "}";
+
+      return tcp;
+   }
+
+   /**
+    * Get the cache name.
+    *
+    * @return the cache name
+    */
+   protected String getCacheName()
+   {
+      return "TimedVFSCache";
+   }
+
+   /**
+    * Set default lifetime.
+    *
+    * @param defaultLifetime the default lifetime
+    */
+   public void setDefaultLifetime(Integer defaultLifetime)
+   {
+      this.defaultLifetime = defaultLifetime;
+   }
+
+   /**
+    * Set threadsafe flag.
+    *
+    * @param threadSafe the threadsafe flag
+    */
+   public void setThreadSafe(Boolean threadSafe)
+   {
+      this.threadSafe = threadSafe;
+   }
+
+   /**
+    * The resollution.
+    *
+    * @param resolution the resolution
+    */
+   public void setResolution(Integer resolution)
+   {
+      this.resolution = resolution;
+   }
+
+   public String toString()
+   {
+      return info;
+   }
+}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractExceptionHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/AbstractExceptionHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractExceptionHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractExceptionHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,41 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.spi.ExceptionHandler;
+
+/**
+ * AbstractExceptionHandler
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class AbstractExceptionHandler implements ExceptionHandler
+{
+   /** The log */
+   protected final Logger log = Logger.getLogger(getClass());
+
+   public void handleZipEntriesInitException(Exception e, String name)
+   {
+      throw new RuntimeException(e);
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,352 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.VirtualFileFilter;
-import org.jboss.virtual.VisitorAttributes;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.virtual.spi.VirtualFileHandlerVisitor;
-
-/**
- * AbstractVFSContext.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.1 $
- */
-public abstract class AbstractVFSContext implements VFSContext
-{
-   /** The log */
-   protected final Logger log = Logger.getLogger(getClass());
-   
-   /** The VFS wrapper */
-   private VFS vfs;
-   
-   /** The root url */
-   private final URI rootURI;
-
-   /** Options associated with the root URL */
-   private Map<String, String> rootOptions;
-
-   /** Root's peer within another context */
-   private VirtualFileHandler rootPeer;
-
-   /**
-    * Create a new AbstractVFSContext.
-    * 
-    * @param rootURI the root url
-    * @throws IllegalArgumentException if rootURI is null
-    */
-   protected AbstractVFSContext(URI rootURI)
-   {
-      if (rootURI == null)
-         throw new IllegalArgumentException("Null rootURI");
-      this.rootURI = rootURI;
-      String query = rootURI.getQuery();
-      rootOptions = VFSUtils.parseURLQuery(query);
-   }
-
-   /**
-    * Create a new AbstractVFSContext.
-    * 
-    * @param rootURL the root url
-    * @throws URISyntaxException for illegal URL
-    * @throws IllegalArgumentException if rootURI is null
-    */
-   protected AbstractVFSContext(URL rootURL) throws URISyntaxException
-   {
-      this(rootURL.toURI());
-   }
-
-   public VFS getVFS()
-   {
-      if (vfs == null)
-         vfs = new VFS(this);
-      return vfs;
-   }
-
-   public URI getRootURI()
-   {
-      return rootURI;
-   }
-
-   public void setRootPeer(VirtualFileHandler handler)
-   {
-      this.rootPeer = handler;
-   }
-
-   public VirtualFileHandler getRootPeer()
-   {
-      return rootPeer;
-   }
-
-   protected void addOption(String key, String value)
-   {
-      rootOptions.put(key, value);
-   }
-
-   public Map<String, String> getOptions()
-   {
-      return rootOptions;
-   }
-
-   /**
-    * Helper method to set options on an URL
-    *
-    * @param url  url to set options on
-    * @return url with query parameters
-    * @throws java.net.MalformedURLException if url manipulation fails
-    */
-   protected URL setOptionsToURL(URL url) throws MalformedURLException
-   {
-      if (rootOptions.size() == 0)
-         return url;
-
-      StringBuilder sb = new StringBuilder(url.toString());
-      sb.append("?");
-      int i = 0;
-      for (Map.Entry<String, String> ent : rootOptions.entrySet())
-      {
-         if (i > 0)
-            sb.append("&");
-         sb.append(ent.getKey()).append("=").append(ent.getValue());
-         i++;
-      }
-      
-      return new URL(sb.toString());
-   }
-
-   public List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Null parent");
-      return parent.getChildren(ignoreErrors);
-   }
-
-   public VirtualFileHandler getChild(VirtualFileHandler parent, String path) throws IOException
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Null parent");
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-      return parent.getChild(path);
-   }
-
-   /**
-    * Construct a URL from a given parent and a name
-    *
-    * @param parent a parent
-    * @param name a name of the child
-    * @return URL corresponding to a child
-    * @throws IOException for any error
-    */
-   public URL getChildURL(VirtualFileHandler parent, String name) throws IOException
-   {      
-      if(parent != null)
-      {
-         VFSContext parentCtx = parent.getVFSContext();
-         if (parentCtx != this)
-         {
-            if (parentCtx instanceof AbstractVFSContext)
-            {
-               return ((AbstractVFSContext) parentCtx).getChildURL(parent, name);
-            }
-            else
-            {
-               StringBuilder urlStr = new StringBuilder(512);
-               try
-               {
-                  urlStr.append(parent.toURI());
-                  if (urlStr.charAt( urlStr.length()-1) != '/')
-                     urlStr.append("/");
-
-                  urlStr.append(name);
-                  return new URL(urlStr.toString());
-               }
-               catch (URISyntaxException e)
-               {
-                  throw new RuntimeException("Failed to create child URL: " + parent + " + " + name, e);
-               }
-            }
-         }
-      }
-
-      StringBuilder urlStr = new StringBuilder(512);
-      URI rootUri = getRootURI();
-      urlStr.append(rootUri.getScheme())
-              .append(":").append(rootUri.getPath());
-
-      if(parent != null)
-      {
-         if (urlStr.charAt( urlStr.length()-1) != '/')
-            urlStr.append("/");
-
-         String pPathName = parent.getPathName();         
-         if(pPathName.length() != 0)
-            urlStr.append(pPathName);
-
-         if (urlStr.charAt( urlStr.length()-1) != '/')
-            urlStr.append("/");
-
-         urlStr.append(name);
-      }
-
-      return new URL(urlStr.toString());
-   }
-
-   public void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor) throws IOException
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-      if (visitor == null)
-         throw new IllegalArgumentException("Null visitor");
-      
-      VisitorAttributes attributes = visitor.getAttributes();
-      boolean includeRoot = attributes.isIncludeRoot();
-      boolean leavesOnly = attributes.isLeavesOnly();
-      boolean ignoreErrors = attributes.isIgnoreErrors();
-      boolean includeHidden = attributes.isIncludeHidden();
-      VirtualFileFilter recurseFilter = attributes.getRecurseFilter();
-      visit(handler, visitor, includeRoot, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
-   }
-
-   /**
-    * Visit. the file system, recursive death checking is left to the visitor
-    * or otherwise a stack overflow.
-    * 
-    * @param handler the reference handler
-    * @param visitor the visitor
-    * @param includeRoot whether to visit the root
-    * @param leavesOnly whether to visit leaves only
-    * @param ignoreErrors whether to ignore errors
-    * @param includeHidden whether to include hidden files
-    * @param recurseFilter the recurse filter
-    * @throws IOException for any problem accessing the virtual file system
-    */
-   protected void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor,
-         boolean includeRoot, boolean leavesOnly, boolean ignoreErrors,
-         boolean includeHidden, VirtualFileFilter recurseFilter)
-      throws IOException
-   {
-      // Visit the root when asked
-      if (includeRoot)
-         visitor.visit(handler);
-      
-      // Visit the children
-      boolean trace = log.isTraceEnabled();
-      List<VirtualFileHandler> children;
-      try
-      {
-          children = getChildren(handler, ignoreErrors);
-      }
-      catch (IOException e)
-      {
-         if (ignoreErrors == false)
-            throw e;
-         if( trace )
-            log.trace("Ignored: " + e);
-         return;
-      }
-      
-      // Look through each child
-      for (VirtualFileHandler child : children)
-      {
-         // Ignore hidden if asked
-         if (includeHidden == false && child.isHidden())
-         {
-            if( trace )
-               log.trace("Ignoring hidden file: "+child);
-            continue;
-         }
-         
-         // Visit the leaf or non-leaves when asked
-         boolean isLeaf = child.isLeaf();
-         if (leavesOnly == false || isLeaf)
-            visitor.visit(child);
-         else if( trace )
-         {
-            log.trace("Skipping non-leaf file: "+child);
-         }
-
-         // Recurse when asked
-         VirtualFile file = child.getVirtualFile();
-         if ( isLeaf == false && recurseFilter != null && recurseFilter.accepts(file))
-         {
-            try
-            {
-               if (handler instanceof DelegatingHandler)
-                  child.getVFSContext().visit(child, visitor);
-               else
-                  visit(child, visitor, false, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
-            }
-            catch (StackOverflowError e)
-            {
-               log.debug("Original: " + child, e);
-               throw new IOException("Stack overflow, the file system is too complicated? " + child);
-            }
-         }
-      }
-   }
-   
-   @Override
-   public String toString()
-   {
-      StringBuilder buffer = new StringBuilder();
-      buffer.append(getClass().getSimpleName());
-      buffer.append('@');
-      buffer.append(System.identityHashCode(this));
-      buffer.append('[');
-      buffer.append(rootURI);
-      buffer.append(']');
-      return buffer.toString();
-   }
-   
-   @Override
-   public int hashCode()
-   {
-      return rootURI.hashCode();
-   }
-
-   @Override
-   public boolean equals(Object obj)
-   {
-      if (this == obj)
-         return true;
-      if (obj == null || obj instanceof VFSContext == false)
-         return false;
-      VFSContext other = (VFSContext) obj;
-      return rootURI.equals(other.getRootURI());
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,378 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VirtualFileFilter;
+import org.jboss.virtual.VisitorAttributes;
+import org.jboss.virtual.spi.ExceptionHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.virtual.spi.VirtualFileHandlerVisitor;
+
+/**
+ * AbstractVFSContext.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractVFSContext implements VFSContext
+{
+   /** The log */
+   protected final Logger log = Logger.getLogger(getClass());
+   
+   /** The VFS wrapper */
+   private VFS vfs;
+   
+   /** The root url */
+   private final URI rootURI;
+
+   /** Options associated with the root URL */
+   private Map<String, String> rootOptions;
+
+   /** Root's peer within another context */
+   private VirtualFileHandler rootPeer;
+
+   /** The exception handler */
+   private ExceptionHandler exceptionHandler;
+
+   /**
+    * Create a new AbstractVFSContext.
+    * 
+    * @param rootURI the root url
+    * @throws IllegalArgumentException if rootURI is null
+    */
+   protected AbstractVFSContext(URI rootURI)
+   {
+      if (rootURI == null)
+         throw new IllegalArgumentException("Null rootURI");
+      this.rootURI = rootURI;
+      String query = rootURI.getQuery();
+      rootOptions = VFSUtils.parseURLQuery(query);
+   }
+
+   /**
+    * Create a new AbstractVFSContext.
+    * 
+    * @param rootURL the root url
+    * @throws URISyntaxException for illegal URL
+    * @throws IllegalArgumentException if rootURI is null
+    */
+   protected AbstractVFSContext(URL rootURL) throws URISyntaxException
+   {
+      this(rootURL.toURI());
+   }
+
+   public VFS getVFS()
+   {
+      if (vfs == null)
+         vfs = new VFS(this);
+      return vfs;
+   }
+
+   public URI getRootURI()
+   {
+      return rootURI;
+   }
+
+   public void setRootPeer(VirtualFileHandler handler)
+   {
+      this.rootPeer = handler;
+   }
+
+   public VirtualFileHandler getRootPeer()
+   {
+      return rootPeer;
+   }
+
+   protected void addOption(String key, String value)
+   {
+      rootOptions.put(key, value);
+   }
+
+   public Map<String, String> getOptions()
+   {
+      return rootOptions;
+   }
+
+   /**
+    * Get peer vfs context.
+    *
+    * @return the peer context
+    */
+   protected VFSContext getPeerContext()
+   {
+      VirtualFileHandler peer = getRootPeer();
+      return peer != null ? peer.getVFSContext() : null;
+   }
+
+   /**
+    * Helper method to set options on an URL
+    *
+    * @param url  url to set options on
+    * @return url with query parameters
+    * @throws java.net.MalformedURLException if url manipulation fails
+    */
+   protected URL setOptionsToURL(URL url) throws MalformedURLException
+   {
+      if (rootOptions.size() == 0)
+         return url;
+
+      StringBuilder sb = new StringBuilder(url.toString());
+      sb.append("?");
+      int i = 0;
+      for (Map.Entry<String, String> ent : rootOptions.entrySet())
+      {
+         if (i > 0)
+            sb.append("&");
+         sb.append(ent.getKey()).append("=").append(ent.getValue());
+         i++;
+      }
+      
+      return new URL(sb.toString());
+   }
+
+   public List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Null parent");
+      return parent.getChildren(ignoreErrors);
+   }
+
+   public VirtualFileHandler getChild(VirtualFileHandler parent, String path) throws IOException
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Null parent");
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+      return parent.getChild(path);
+   }
+
+   /**
+    * Construct a URL from a given parent and a name
+    *
+    * @param parent a parent
+    * @param name a name of the child
+    * @return URL corresponding to a child
+    * @throws IOException for any error
+    */
+   public URL getChildURL(VirtualFileHandler parent, String name) throws IOException
+   {      
+      if(parent != null)
+      {
+         VFSContext parentCtx = parent.getVFSContext();
+         if (parentCtx != this)
+         {
+            if (parentCtx instanceof AbstractVFSContext)
+            {
+               return ((AbstractVFSContext) parentCtx).getChildURL(parent, name);
+            }
+            else
+            {
+               StringBuilder urlStr = new StringBuilder(512);
+               try
+               {
+                  urlStr.append(parent.toURI());
+                  if (urlStr.charAt( urlStr.length()-1) != '/')
+                     urlStr.append("/");
+
+                  urlStr.append(name);
+                  return new URL(urlStr.toString());
+               }
+               catch (URISyntaxException e)
+               {
+                  throw new RuntimeException("Failed to create child URL: " + parent + " + " + name, e);
+               }
+            }
+         }
+      }
+
+      StringBuilder urlStr = new StringBuilder(512);
+      URI rootUri = getRootURI();
+      urlStr.append(rootUri.getScheme())
+              .append(":").append(rootUri.getPath());
+
+      if(parent != null)
+      {
+         if (urlStr.charAt( urlStr.length()-1) != '/')
+            urlStr.append("/");
+
+         String pPathName = parent.getPathName();         
+         if(pPathName.length() != 0)
+            urlStr.append(pPathName);
+
+         if (urlStr.charAt( urlStr.length()-1) != '/')
+            urlStr.append("/");
+
+         urlStr.append(name);
+      }
+
+      return new URL(urlStr.toString());
+   }
+
+   public void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor) throws IOException
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+      if (visitor == null)
+         throw new IllegalArgumentException("Null visitor");
+      
+      VisitorAttributes attributes = visitor.getAttributes();
+      boolean includeRoot = attributes.isIncludeRoot();
+      boolean leavesOnly = attributes.isLeavesOnly();
+      boolean ignoreErrors = attributes.isIgnoreErrors();
+      boolean includeHidden = attributes.isIncludeHidden();
+      VirtualFileFilter recurseFilter = attributes.getRecurseFilter();
+      visit(handler, visitor, includeRoot, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
+   }
+
+   /**
+    * Visit. the file system, recursive death checking is left to the visitor
+    * or otherwise a stack overflow.
+    * 
+    * @param handler the reference handler
+    * @param visitor the visitor
+    * @param includeRoot whether to visit the root
+    * @param leavesOnly whether to visit leaves only
+    * @param ignoreErrors whether to ignore errors
+    * @param includeHidden whether to include hidden files
+    * @param recurseFilter the recurse filter
+    * @throws IOException for any problem accessing the virtual file system
+    */
+   protected void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor,
+         boolean includeRoot, boolean leavesOnly, boolean ignoreErrors,
+         boolean includeHidden, VirtualFileFilter recurseFilter)
+      throws IOException
+   {
+      // Visit the root when asked
+      if (includeRoot)
+         visitor.visit(handler);
+      
+      // Visit the children
+      boolean trace = log.isTraceEnabled();
+      List<VirtualFileHandler> children;
+      try
+      {
+          children = getChildren(handler, ignoreErrors);
+      }
+      catch (IOException e)
+      {
+         if (ignoreErrors == false)
+            throw e;
+         if( trace )
+            log.trace("Ignored: " + e);
+         return;
+      }
+      
+      // Look through each child
+      for (VirtualFileHandler child : children)
+      {
+         // Ignore hidden if asked
+         if (includeHidden == false && child.isHidden())
+         {
+            if( trace )
+               log.trace("Ignoring hidden file: "+child);
+            continue;
+         }
+         
+         // Visit the leaf or non-leaves when asked
+         boolean isLeaf = child.isLeaf();
+         if (leavesOnly == false || isLeaf)
+            visitor.visit(child);
+         else if( trace )
+         {
+            log.trace("Skipping non-leaf file: "+child);
+         }
+
+         // Recurse when asked
+         VirtualFile file = child.getVirtualFile();
+         if ( isLeaf == false && recurseFilter != null && recurseFilter.accepts(file))
+         {
+            try
+            {
+               if (handler instanceof DelegatingHandler)
+                  child.getVFSContext().visit(child, visitor);
+               else
+                  visit(child, visitor, false, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
+            }
+            catch (StackOverflowError e)
+            {
+               log.debug("Original: " + child, e);
+               throw new IOException("Stack overflow, the file system is too complicated? " + child);
+            }
+         }
+      }
+   }
+
+   public ExceptionHandler getExceptionHandler()
+   {
+      return exceptionHandler;
+   }
+
+   public void setExceptionHandler(ExceptionHandler exceptionHandler)
+   {
+      this.exceptionHandler = exceptionHandler;
+   }
+
+   @Override
+   public String toString()
+   {
+      StringBuilder buffer = new StringBuilder();
+      buffer.append(getClass().getSimpleName());
+      buffer.append('@');
+      buffer.append(System.identityHashCode(this));
+      buffer.append('[');
+      buffer.append(rootURI);
+      buffer.append(']');
+      return buffer.toString();
+   }
+   
+   @Override
+   public int hashCode()
+   {
+      return rootURI.hashCode();
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null || obj instanceof VFSContext == false)
+         return false;
+      VFSContext other = (VFSContext) obj;
+      return rootURI.equals(other.getRootURI());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,695 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.ObjectStreamField;
-import java.io.ObjectInputStream.GetField;
-import java.io.ObjectOutputStream.PutField;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VFSContextFactory;
-import org.jboss.virtual.spi.VFSContextFactoryLocator;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * AbstractVirtualFileHandler.
- * 
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author Scott.Stark at jboss.org
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.1 $
- */
-public abstract class AbstractVirtualFileHandler implements VirtualFileHandler
-{
-   /** The log */
-   protected static final Logger log = Logger.getLogger(AbstractVirtualFileHandler.class);
-   /** serialVersionUID */
-   private static final long serialVersionUID = 1L;
-   /** The class serial fields */
-   private static final ObjectStreamField[] serialPersistentFields =
-   {
-      new ObjectStreamField("rootURI", URI.class),
-      new ObjectStreamField("parent", VirtualFileHandler.class),
-      new ObjectStreamField("name", String.class),
-      new ObjectStreamField("vfsUrl", URL.class)
-   };
-
-   /**
-    * The VFS context
-    *
-    * @serialField rootURI URI the VFS context rootURI
-    */
-   private VFSContext context;
-   
-   /**
-    * The parent
-    *
-    * @serialField parent VirtualFileHandler the virtual file parent
-    */
-   private VirtualFileHandler parent;
-
-   /**
-    * The name
-    *
-    * @serialField name String the virtual file name
-    */
-   private String name;
-
-   /**
-    * The vfs URL
-    *
-    * @serialField vfsUrl the vfs based url
-    */
-   private URL vfsUrl;
-
-   /** The vfsPath */
-   private transient String vfsPath;
-
-   /** The reference count */
-   private transient AtomicInteger references = new AtomicInteger(0);
-
-   /** The cached last modified */
-   protected transient long cachedLastModified;
-
-   /**
-    * Create a new handler
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param name the name
-    * @throws IllegalArgumentException if the context or name is null;
-    */
-   protected AbstractVirtualFileHandler(VFSContext context, VirtualFileHandler parent, String name)
-   {
-      if (context == null)
-         throw new IllegalArgumentException("Null context");
-      if (name == null)
-         throw new IllegalArgumentException("Null name");
-      this.context = context;
-      this.parent = parent;
-      this.name = VFSUtils.fixName(name);
-      this.vfsPath = null; // nullify possible invalid vfsPath initializations when running with debugger
-   }
-
-   /**
-    * Check if parent exists.
-    */
-   protected void checkParentExists()
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Parent must exist!");
-   }
-
-   /**
-    * Get child url.
-    *
-    * @param childPath the child path
-    * @param isDirectory is directory
-    * @return full child URL
-    * @throws IOException for any io error
-    * @throws URISyntaxException for any uri error
-    */
-   protected URL getChildVfsUrl(String childPath, boolean isDirectory) throws IOException, URISyntaxException
-   {
-      checkParentExists();
-      URL parentVfsUrl = getParent().toVfsUrl();
-      String vfsUrlString = parentVfsUrl.toString();
-      if (vfsUrlString.length() > 0 && vfsUrlString.endsWith("/") == false)
-         vfsUrlString += "/";
-      vfsUrlString += childPath;
-      if (isDirectory && vfsUrlString.endsWith("/") == false)
-         vfsUrlString += "/";
-      return new URL(vfsUrlString);
-   }
-
-   /**
-    * Get child path name.
-    *
-    * @param childPath the child path
-    * @param isDirectory is directory
-    * @return full child URL
-    * @throws IOException for any io error
-    */
-   protected String getChildPathName(String childPath, boolean isDirectory) throws IOException
-   {
-      checkParentExists();
-      String childPathName = getParent().getPathName();
-      if (childPathName.length() > 0 && childPathName.endsWith("/") == false)
-         childPathName += "/";
-      childPathName += childPath;
-      if (isDirectory && childPathName.endsWith("/") == false)
-         childPathName += "/";
-      return childPathName;
-   }
-
-   public boolean hasBeenModified() throws IOException
-   {
-      boolean hasBeenModified = false;
-      long last = getLastModified();
-      if(log.isTraceEnabled())
-         log.trace("hasBeenModified, lastModified: "+last+", cachedLastModified: "+cachedLastModified);
-      if (cachedLastModified != last)
-      {
-         hasBeenModified = cachedLastModified != 0;
-         cachedLastModified = last;
-      }
-      return hasBeenModified;
-   }
-
-   public String getName()
-   {
-      return name;
-   }
-
-   /**
-    * Get a pathName relative to most outer context (contexts can be mounted one within other)
-    *
-    * @return  pathName
-    */
-   public String getPathName()
-   {
-      if (vfsPath == null)
-      {
-         StringBuilder pathName = new StringBuilder();
-         initPath(pathName);
-         vfsPath = pathName.toString();
-      }
-      return vfsPath;
-   }
-
-   /**
-    * todo This is a hack until we can fix http://jira.jboss.com/jira/browse/JBMICROCONT-164
-    *
-    * @param path
-    */
-   public void setPathName(String path)
-   {
-      this.vfsPath = path;
-   }
-
-   /**
-    * Get a pathName relative to local context
-    *
-    * @return pathName
-    */
-   public String getLocalPathName()
-   {
-      try
-      {
-         VirtualFileHandler handler = getLocalVFSContext().getRoot();
-         String rootPathName = handler.getPathName();
-         String pathName = getPathName();
-         int len = rootPathName.length();
-         if (len == 0)
-            return pathName;
-         else if (rootPathName.length() < pathName.length())
-            return pathName.substring(len + 1);
-         else
-            return "";
-      }
-      catch (IOException ex)
-      {
-         log.warn("Failed to compose local path name: context: " + getLocalVFSContext() + ", name: " + getName(), ex);
-      }
-
-      return getPathName();
-   }
-
-   public URL toURL() throws MalformedURLException, URISyntaxException
-   {
-      return toURI().toURL();
-   }
-
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      return vfsUrl;
-   }
-
-   /**
-    * Get VFS url.
-    *
-    * @return vfs url
-    */
-   protected URL getVfsUrl()
-   {
-      return vfsUrl;
-   }
-
-   /**
-    * Set the vfs URL.
-    *
-    * @param vfsUrl vfs url
-    */
-   protected void setVfsUrl(URL vfsUrl)
-   {
-      this.vfsUrl = vfsUrl;
-   }
-
-   /**
-    * Initialise the path into the path name
-    * 
-    * @param pathName the path name
-    * @return whether it added anything
-    */
-   private boolean initPath(StringBuilder pathName)
-   {
-      if (context.getRootPeer() != null)
-         if (initPeerPath(pathName))
-            return true;
-
-      if (parent != null)
-      {
-         if (parent instanceof AbstractVirtualFileHandler)
-         {
-            AbstractVirtualFileHandler handler = (AbstractVirtualFileHandler) parent;
-            if (handler.initPath(pathName))
-               pathName.append('/');
-         }
-         else
-         {
-            pathName.append(parent.getPathName());
-         }
-         pathName.append(getName());
-         return true;
-      }
-      return false;
-   }
-
-
-   private boolean initPeerPath(StringBuilder pathName)
-   {
-      VirtualFileHandler grandParent = null;
-
-      if (parent != null)
-      {
-         try
-         {
-            grandParent = parent.getParent();
-         }
-         catch(IOException ex)
-         {
-            // if we throw exception here we'll most likely cause an infinite recursion
-            log.warn("AbstractVirtualFileHandler.initPath failed: ctx: " + context
-                    + ", parent: " + parent + " name: " + name, ex);
-         }
-      }
-
-      VirtualFileHandler peer = context.getRootPeer();
-
-
-      if (grandParent == null)
-      {
-         // bypass parent and delegate straight to peer
-
-         if (peer instanceof AbstractVirtualFileHandler)
-         {
-            AbstractVirtualFileHandler handler = (AbstractVirtualFileHandler) peer;
-            if (handler.initPath(pathName) && parent != null)
-               pathName.append('/');
-         }
-         else
-         {
-            pathName.append(peer.getPathName());
-         }
-
-         if (parent != null)
-         {
-            // if it's a root node we skip adding '/' and a name
-            pathName.append(getName());
-         }
-
-         return true;
-      }
-
-      return false;
-   }
-
-   public VirtualFile getVirtualFile()
-   {
-      checkClosed();
-      increment();
-      return new VirtualFile(this);
-   }
-
-   /**
-    * Get this handler's parent.
-    * If this handler represents a root of the context mounted within another context
-    * a parent from the outer context will be returned.
-    *
-    * @return parent handler
-    * @throws IOException for any error
-    */
-   public VirtualFileHandler getParent() throws IOException
-   {
-      checkClosed();
-      if (parent == null)
-      {
-         if (context instanceof AbstractVFSContext)
-         {
-            AbstractVFSContext avfs = (AbstractVFSContext) context;
-            VirtualFileHandler peer = avfs.getRootPeer();
-            if (peer != null)
-               return peer.getParent();
-         }
-      }
-      return parent;
-   }
-
-   /**
-    * Get this handler's most outer context (contexts can be mounted one within other).
-    *
-    * @return context
-    */
-   public VFSContext getVFSContext()
-   {
-      checkClosed();
-      if (context instanceof AbstractVFSContext)
-      {
-         AbstractVFSContext avfs = (AbstractVFSContext) context;
-         VirtualFileHandler peer = avfs.getRootPeer();
-         if (peer != null)
-            return peer.getVFSContext();
-      }
-      return context;
-   }
-
-   /**
-    * Get this handler's local context
-    *
-    * @return context
-    */
-   public VFSContext getLocalVFSContext()
-   {
-      return context;
-   }
-
-   /**
-    * Increment the reference count
-    * 
-    * @return the resulting count
-    */
-   protected int increment()
-   {
-      return references.incrementAndGet();
-   }
-
-   /**
-    * Decrement the reference count
-    * 
-    * @return the resulting count
-    */
-   protected int decrement()
-   {
-      return references.decrementAndGet();
-   }
-
-   /**
-    * Check whether we are closed
-    * 
-    * @throws IllegalStateException when closed
-    */
-   protected void checkClosed() throws IllegalStateException 
-   {
-      if (references.get() < 0)
-         throw new IllegalStateException("Closed " + toStringLocal());
-   }
-   
-   public void close() 
-   {
-      if (decrement() == 0)
-         doClose();
-   }
-
-   /**
-    * The real close
-    */
-   protected void doClose()
-   {
-      // nothing
-   }
-
-   /**
-    * Delete the file represented by this handler.
-    *
-    * File deletion is comprised of two parts:
-    *
-    * <ol>
-    * <li>physical file deletion - performed by this method or its override</li>
-    * <li>removal of any child references from the parent - performed by {@link #removeChild(String)} of the parent</li>
-    * </ol>
-    *
-    * This method doesn't do any physical file removal because it has no concept of underlying physical file.
-    * An implementation that does physical file removal should override this method and call super.delete() at the end.
-    *
-    * @param gracePeriod max time to wait for any locks
-    * @return true if file was deleted, false otherwise
-    * @throws IOException if an error occurs
-    */
-   public boolean delete(int gracePeriod) throws IOException
-   {
-      VirtualFileHandler parent = getParent();
-      if (parent != null)
-         return parent.removeChild(getName());
-
-      return false;
-   }
-
-   /**
-    * Structured implementation of get child
-    *
-    * @param path the path
-    * @return the handler or <code>null</code> if it doesn't exist
-    * @throws IOException for any error accessing the virtual file system
-    * @throws IllegalArgumentException for a null name
-    */
-   public VirtualFileHandler structuredFindChild(String path) throws IOException
-   {
-      checkClosed();
-
-      // Parse the path
-      List<String> tokens = PathTokenizer.getTokens(path);
-      if (tokens == null || tokens.size() == 0)
-         return this;
-
-      // Go through each context starting from ours
-      // check the parents are not leaves.
-      VirtualFileHandler current = this;
-      for (int i = 0; i < tokens.size(); ++i)
-      {
-         if (current == null)
-            return null;
-
-         String token = tokens.get(i);
-         if (PathTokenizer.isCurrentToken(token))
-            continue;
-
-         if (PathTokenizer.isReverseToken(token))
-         {
-            VirtualFileHandler parent = current.getParent();
-            if (parent == null) // TODO - still IOE or null?
-               throw new IOException("Using reverse path on top file handler: " + current + ", " + path);
-            else
-               current = parent;
-
-            continue;
-         }
-
-         if (current.isLeaf())
-         {
-            return null;
-         }
-         else if (current instanceof StructuredVirtualFileHandler)
-         {
-            StructuredVirtualFileHandler structured = (StructuredVirtualFileHandler)current;
-            current = structured.createChildHandler(token);
-         }
-         else
-         {
-            String remainingPath = PathTokenizer.getRemainingPath(tokens, i);
-            return current.getChild(remainingPath);
-         }
-      }
-
-      // The last one is the result
-      return current;
-   }
-
-   /**
-    * Simple implementation of findChild
-    * 
-    * @param path the path
-    * @return the handler
-    * @throws IOException for any error accessing the virtual file system
-    * @throws IllegalArgumentException for a null name
-    */
-   public VirtualFileHandler simpleFindChild(String path) throws IOException
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-
-      if (path.length() == 0)
-         return this;
-
-      // check for reverse .. path
-      String appliedPath = PathTokenizer.applySpecialPaths(path);
-      List<VirtualFileHandler> children = getChildren(false);
-      for (VirtualFileHandler child : children)
-      {
-         if (child.getName().equals(appliedPath))
-            return child;
-      }
-      return null;
-   }
-
-   public void replaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      internalReplaceChild(original, replacement);
-      if (replacement instanceof AbstractVirtualFileHandler)
-      {
-         AbstractVirtualFileHandler avfh = (AbstractVirtualFileHandler)replacement;
-         avfh.parent = this;
-      }
-   }
-
-   /**
-    * Replace original child with unpacked replacement.
-    *
-    * @param original the original
-    * @param replacement the replacement
-    */
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      throw new UnsupportedOperationException("Replacement is unsupported: " + toString());
-   }
-
-   @Override
-   public String toString()
-   {
-      StringBuilder buffer = new StringBuilder();
-      buffer.append(getClass().getSimpleName());
-      buffer.append('@');
-      buffer.append(System.identityHashCode(this));
-      buffer.append("[path=").append(getPathName());
-      buffer.append(" context=").append(getVFSContext().getRootURI());
-      buffer.append(" real=").append(safeToURLString());
-      buffer.append(']');
-      return buffer.toString();
-   }
-
-   public String toStringLocal()
-   {
-      StringBuilder buffer = new StringBuilder();
-      buffer.append(getClass().getSimpleName());
-      buffer.append('@');
-      buffer.append(System.identityHashCode(this));
-      buffer.append("[path=").append(getLocalPathName());
-      buffer.append(" context=").append(context.getRootURI());
-      //buffer.append(" real=").append(safeToURLString());
-      buffer.append(']');
-      return buffer.toString();
-   }
-
-   @Override
-   public int hashCode()
-   {
-      return getPathName().hashCode();
-   }
-
-   @Override
-   public boolean equals(Object obj)
-   {
-      if (this == obj)
-         return true;
-      if (obj == null || obj instanceof VirtualFileHandler == false)
-         return false;
-      VirtualFileHandler other = (VirtualFileHandler) obj;
-      if (getVFSContext().equals(other.getVFSContext()) == false)
-         return false;
-      if (getPathName().equals(other.getPathName()) == false)
-         return false;
-      return true;
-   }
-
-   /*
-   @Override
-   protected void finalize() throws Throwable
-   {
-      close();
-   }
-   */
-   
-   /**
-    * Safely get a url version of the string
-    * 
-    * @return the string or unknown if there is an error
-    */
-   private String safeToURLString()
-   {
-      try
-      {
-         return toURI().toString();
-      }
-      catch (URISyntaxException ignored)
-      {
-         return "<unknown>";
-      }
-   }
-
-   private void writeObject(ObjectOutputStream out)
-      throws IOException
-   {
-      PutField fields = out.putFields();
-      fields.put("rootURI", getLocalVFSContext().getRootURI());
-      fields.put("parent", parent);
-      fields.put("name", name);
-      fields.put("vfsUrl", vfsUrl);
-      out.writeFields();
-   }
-
-   private void readObject(ObjectInputStream in)
-      throws IOException, ClassNotFoundException
-   {
-      // Read in the serialPersistentFields
-      GetField fields = in.readFields();
-      URI rootURI = (URI) fields.get("rootURI", null);
-      this.parent = (VirtualFileHandler) fields.get("parent", null);
-      this.name = (String) fields.get("name", null);
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURI);
-      this.context = factory.getVFS(rootURI);
-      this.references = new AtomicInteger(0);
-      this.vfsUrl = (URL)fields.get("vfsUrl", null);
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,700 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectInputStream.GetField;
+import java.io.ObjectOutputStream;
+import java.io.ObjectOutputStream.PutField;
+import java.io.ObjectStreamField;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VFSContextFactory;
+import org.jboss.virtual.spi.VFSContextFactoryLocator;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * AbstractVirtualFileHandler.
+ * 
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractVirtualFileHandler implements VirtualFileHandler
+{
+   /** The log */
+   protected static final Logger log = Logger.getLogger(AbstractVirtualFileHandler.class);
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+   /** The class serial fields */
+   private static final ObjectStreamField[] serialPersistentFields =
+   {
+      new ObjectStreamField("rootURI", URI.class),
+      new ObjectStreamField("parent", VirtualFileHandler.class),
+      new ObjectStreamField("name", String.class),
+      new ObjectStreamField("vfsUrl", URL.class)
+   };
+
+   /**
+    * The VFS context
+    *
+    * @serialField rootURI URI the VFS context rootURI
+    */
+   private VFSContext context;
+   
+   /**
+    * The parent
+    *
+    * @serialField parent VirtualFileHandler the virtual file parent
+    */
+   private VirtualFileHandler parent;
+
+   /**
+    * The name
+    *
+    * @serialField name String the virtual file name
+    */
+   private String name;
+
+   /**
+    * The vfs URL
+    *
+    * @serialField vfsUrl the vfs based url
+    */
+   private URL vfsUrl;
+
+   /** The vfsPath */
+   private transient String vfsPath;
+
+   /** The reference count */
+   private transient AtomicInteger references = new AtomicInteger(0);
+
+   /** The cached last modified */
+   protected transient long cachedLastModified;
+
+   /**
+    * Create a new handler
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param name the name
+    * @throws IllegalArgumentException if the context or name is null;
+    */
+   protected AbstractVirtualFileHandler(VFSContext context, VirtualFileHandler parent, String name)
+   {
+      if (context == null)
+         throw new IllegalArgumentException("Null context");
+      if (name == null)
+         throw new IllegalArgumentException("Null name");
+      this.context = context;
+      this.parent = parent;
+      this.name = VFSUtils.fixName(name);
+      this.vfsPath = null; // nullify possible invalid vfsPath initializations when running with debugger
+   }
+
+   /**
+    * Check if parent exists.
+    */
+   protected void checkParentExists()
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Parent must exist!");
+   }
+
+   /**
+    * Get child url.
+    *
+    * @param childPath the child path
+    * @param isDirectory is directory
+    * @return full child URL
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   protected URL getChildVfsUrl(String childPath, boolean isDirectory) throws IOException, URISyntaxException
+   {
+      checkParentExists();
+      URL parentVfsUrl = getParent().toVfsUrl();
+      String vfsUrlString = parentVfsUrl.toString();
+      if (vfsUrlString.length() > 0 && vfsUrlString.endsWith("/") == false)
+         vfsUrlString += "/";
+      vfsUrlString += childPath;
+      if (isDirectory && vfsUrlString.endsWith("/") == false)
+         vfsUrlString += "/";
+      return new URL(vfsUrlString);
+   }
+
+   /**
+    * Get child path name.
+    *
+    * @param childPath the child path
+    * @param isDirectory is directory
+    * @return full child URL
+    * @throws IOException for any io error
+    */
+   protected String getChildPathName(String childPath, boolean isDirectory) throws IOException
+   {
+      checkParentExists();
+      String childPathName = getParent().getPathName();
+      if (childPathName.length() > 0 && childPathName.endsWith("/") == false)
+         childPathName += "/";
+      childPathName += childPath;
+      if (isDirectory && childPathName.endsWith("/") == false)
+         childPathName += "/";
+      return childPathName;
+   }
+
+   public boolean hasBeenModified() throws IOException
+   {
+      boolean hasBeenModified = false;
+      long last = getLastModified();
+      if(log.isTraceEnabled())
+         log.trace("hasBeenModified, lastModified: "+last+", cachedLastModified: "+cachedLastModified);
+      if (cachedLastModified != last)
+      {
+         hasBeenModified = cachedLastModified != 0;
+         cachedLastModified = last;
+      }
+      return hasBeenModified;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   /**
+    * Get a pathName relative to most outer context (contexts can be mounted one within other)
+    *
+    * @return  pathName
+    */
+   public String getPathName()
+   {
+      if (vfsPath == null)
+      {
+         StringBuilder pathName = new StringBuilder();
+         initPath(pathName);
+         vfsPath = pathName.toString();
+      }
+      return vfsPath;
+   }
+
+   /**
+    * todo This is a hack until we can fix http://jira.jboss.com/jira/browse/JBMICROCONT-164
+    *
+    * @param path
+    */
+   public void setPathName(String path)
+   {
+      this.vfsPath = path;
+   }
+
+   /**
+    * Get a pathName relative to local context
+    *
+    * @return pathName
+    */
+   public String getLocalPathName()
+   {
+      try
+      {
+         VirtualFileHandler handler = getLocalVFSContext().getRoot();
+         String rootPathName = handler.getPathName();
+         String pathName = getPathName();
+         int len = rootPathName.length();
+         if (len == 0)
+            return pathName;
+         else if (rootPathName.length() < pathName.length())
+            return pathName.substring(len + 1);
+         else
+            return "";
+      }
+      catch (IOException ex)
+      {
+         log.warn("Failed to compose local path name: context: " + getLocalVFSContext() + ", name: " + getName(), ex);
+      }
+
+      return getPathName();
+   }
+
+   public URL toURL() throws MalformedURLException, URISyntaxException
+   {
+      return toURI().toURL();
+   }
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      return vfsUrl;
+   }
+
+   public URL getRealURL() throws IOException, URISyntaxException
+   {
+      return toURL();
+   }
+
+   /**
+    * Get VFS url.
+    *
+    * @return vfs url
+    */
+   protected URL getVfsUrl()
+   {
+      return vfsUrl;
+   }
+
+   /**
+    * Set the vfs URL.
+    *
+    * @param vfsUrl vfs url
+    */
+   protected void setVfsUrl(URL vfsUrl)
+   {
+      this.vfsUrl = vfsUrl;
+   }
+
+   /**
+    * Initialise the path into the path name
+    * 
+    * @param pathName the path name
+    * @return whether it added anything
+    */
+   private boolean initPath(StringBuilder pathName)
+   {
+      if (context.getRootPeer() != null)
+         if (initPeerPath(pathName))
+            return true;
+
+      if (parent != null)
+      {
+         if (parent instanceof AbstractVirtualFileHandler)
+         {
+            AbstractVirtualFileHandler handler = (AbstractVirtualFileHandler) parent;
+            if (handler.initPath(pathName))
+               pathName.append('/');
+         }
+         else
+         {
+            pathName.append(parent.getPathName());
+         }
+         pathName.append(getName());
+         return true;
+      }
+      return false;
+   }
+
+
+   private boolean initPeerPath(StringBuilder pathName)
+   {
+      VirtualFileHandler grandParent = null;
+
+      if (parent != null)
+      {
+         try
+         {
+            grandParent = parent.getParent();
+         }
+         catch(IOException ex)
+         {
+            // if we throw exception here we'll most likely cause an infinite recursion
+            log.warn("AbstractVirtualFileHandler.initPath failed: ctx: " + context
+                    + ", parent: " + parent + " name: " + name, ex);
+         }
+      }
+
+      VirtualFileHandler peer = context.getRootPeer();
+
+
+      if (grandParent == null)
+      {
+         // bypass parent and delegate straight to peer
+
+         if (peer instanceof AbstractVirtualFileHandler)
+         {
+            AbstractVirtualFileHandler handler = (AbstractVirtualFileHandler) peer;
+            if (handler.initPath(pathName) && parent != null)
+               pathName.append('/');
+         }
+         else
+         {
+            pathName.append(peer.getPathName());
+         }
+
+         if (parent != null)
+         {
+            // if it's a root node we skip adding '/' and a name
+            pathName.append(getName());
+         }
+
+         return true;
+      }
+
+      return false;
+   }
+
+   public VirtualFile getVirtualFile()
+   {
+      checkClosed();
+      increment();
+      return new VirtualFile(this);
+   }
+
+   /**
+    * Get this handler's parent.
+    * If this handler represents a root of the context mounted within another context
+    * a parent from the outer context will be returned.
+    *
+    * @return parent handler
+    * @throws IOException for any error
+    */
+   public VirtualFileHandler getParent() throws IOException
+   {
+      checkClosed();
+      if (parent == null)
+      {
+         if (context instanceof AbstractVFSContext)
+         {
+            AbstractVFSContext avfs = (AbstractVFSContext) context;
+            VirtualFileHandler peer = avfs.getRootPeer();
+            if (peer != null)
+               return peer.getParent();
+         }
+      }
+      return parent;
+   }
+
+   /**
+    * Get this handler's most outer context (contexts can be mounted one within other).
+    *
+    * @return context
+    */
+   public VFSContext getVFSContext()
+   {
+      checkClosed();
+      if (context instanceof AbstractVFSContext)
+      {
+         AbstractVFSContext avfs = (AbstractVFSContext) context;
+         VirtualFileHandler peer = avfs.getRootPeer();
+         if (peer != null)
+            return peer.getVFSContext();
+      }
+      return context;
+   }
+
+   /**
+    * Get this handler's local context
+    *
+    * @return context
+    */
+   public VFSContext getLocalVFSContext()
+   {
+      return context;
+   }
+
+   /**
+    * Increment the reference count
+    * 
+    * @return the resulting count
+    */
+   protected int increment()
+   {
+      return references.incrementAndGet();
+   }
+
+   /**
+    * Decrement the reference count
+    * 
+    * @return the resulting count
+    */
+   protected int decrement()
+   {
+      return references.decrementAndGet();
+   }
+
+   /**
+    * Check whether we are closed
+    * 
+    * @throws IllegalStateException when closed
+    */
+   protected void checkClosed() throws IllegalStateException 
+   {
+      if (references.get() < 0)
+         throw new IllegalStateException("Closed " + toStringLocal());
+   }
+   
+   public void close() 
+   {
+      if (decrement() == 0)
+         doClose();
+   }
+
+   /**
+    * The real close
+    */
+   protected void doClose()
+   {
+      // nothing
+   }
+
+   /**
+    * Delete the file represented by this handler.
+    *
+    * File deletion is comprised of two parts:
+    *
+    * <ol>
+    * <li>physical file deletion - performed by this method or its override</li>
+    * <li>removal of any child references from the parent - performed by {@link #removeChild(String)} of the parent</li>
+    * </ol>
+    *
+    * This method doesn't do any physical file removal because it has no concept of underlying physical file.
+    * An implementation that does physical file removal should override this method and call super.delete() at the end.
+    *
+    * @param gracePeriod max time to wait for any locks
+    * @return true if file was deleted, false otherwise
+    * @throws IOException if an error occurs
+    */
+   public boolean delete(int gracePeriod) throws IOException
+   {
+      VirtualFileHandler parent = getParent();
+      if (parent != null)
+         return parent.removeChild(getName());
+
+      return false;
+   }
+
+   /**
+    * Structured implementation of get child
+    *
+    * @param path the path
+    * @return the handler or <code>null</code> if it doesn't exist
+    * @throws IOException for any error accessing the virtual file system
+    * @throws IllegalArgumentException for a null name
+    */
+   public VirtualFileHandler structuredFindChild(String path) throws IOException
+   {
+      checkClosed();
+
+      // Parse the path
+      List<String> tokens = PathTokenizer.getTokens(path);
+      if (tokens == null || tokens.size() == 0)
+         return this;
+
+      // Go through each context starting from ours
+      // check the parents are not leaves.
+      VirtualFileHandler current = this;
+      for (int i = 0; i < tokens.size(); ++i)
+      {
+         if (current == null)
+            return null;
+
+         String token = tokens.get(i);
+         if (PathTokenizer.isCurrentToken(token))
+            continue;
+
+         if (PathTokenizer.isReverseToken(token))
+         {
+            VirtualFileHandler parent = current.getParent();
+            if (parent == null) // TODO - still IOE or null?
+               throw new IOException("Using reverse path on top file handler: " + current + ", " + path);
+            else
+               current = parent;
+
+            continue;
+         }
+
+         if (current.isLeaf())
+         {
+            return null;
+         }
+         else if (current instanceof StructuredVirtualFileHandler)
+         {
+            StructuredVirtualFileHandler structured = (StructuredVirtualFileHandler)current;
+            current = structured.createChildHandler(token);
+         }
+         else
+         {
+            String remainingPath = PathTokenizer.getRemainingPath(tokens, i);
+            return current.getChild(remainingPath);
+         }
+      }
+
+      // The last one is the result
+      return current;
+   }
+
+   /**
+    * Simple implementation of findChild
+    * 
+    * @param path the path
+    * @return the handler
+    * @throws IOException for any error accessing the virtual file system
+    * @throws IllegalArgumentException for a null name
+    */
+   public VirtualFileHandler simpleFindChild(String path) throws IOException
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+
+      if (path.length() == 0)
+         return this;
+
+      // check for reverse .. path
+      String appliedPath = PathTokenizer.applySpecialPaths(path);
+      List<VirtualFileHandler> children = getChildren(false);
+      for (VirtualFileHandler child : children)
+      {
+         if (child.getName().equals(appliedPath))
+            return child;
+      }
+      return null;
+   }
+
+   public void replaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      internalReplaceChild(original, replacement);
+      if (replacement instanceof AbstractVirtualFileHandler)
+      {
+         AbstractVirtualFileHandler avfh = (AbstractVirtualFileHandler)replacement;
+         avfh.parent = this;
+      }
+   }
+
+   /**
+    * Replace original child with unpacked replacement.
+    *
+    * @param original the original
+    * @param replacement the replacement
+    */
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      throw new UnsupportedOperationException("Replacement is unsupported: " + toString());
+   }
+
+   @Override
+   public String toString()
+   {
+      StringBuilder buffer = new StringBuilder();
+      buffer.append(getClass().getSimpleName());
+      buffer.append('@');
+      buffer.append(System.identityHashCode(this));
+      buffer.append("[path=").append(getPathName());
+      buffer.append(" context=").append(getVFSContext().getRootURI());
+      buffer.append(" real=").append(safeToURLString());
+      buffer.append(']');
+      return buffer.toString();
+   }
+
+   public String toStringLocal()
+   {
+      StringBuilder buffer = new StringBuilder();
+      buffer.append(getClass().getSimpleName());
+      buffer.append('@');
+      buffer.append(System.identityHashCode(this));
+      buffer.append("[path=").append(getLocalPathName());
+      buffer.append(" context=").append(context.getRootURI());
+      //buffer.append(" real=").append(safeToURLString());
+      buffer.append(']');
+      return buffer.toString();
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return getPathName().hashCode();
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      if (this == obj)
+         return true;
+      if (obj == null || obj instanceof VirtualFileHandler == false)
+         return false;
+      VirtualFileHandler other = (VirtualFileHandler) obj;
+      if (getVFSContext().equals(other.getVFSContext()) == false)
+         return false;
+      if (getPathName().equals(other.getPathName()) == false)
+         return false;
+      return true;
+   }
+
+   /*
+   @Override
+   protected void finalize() throws Throwable
+   {
+      close();
+   }
+   */
+   
+   /**
+    * Safely get a url version of the string
+    * 
+    * @return the string or unknown if there is an error
+    */
+   private String safeToURLString()
+   {
+      try
+      {
+         return toURI().toString();
+      }
+      catch (URISyntaxException ignored)
+      {
+         return "<unknown>";
+      }
+   }
+
+   private void writeObject(ObjectOutputStream out)
+      throws IOException
+   {
+      PutField fields = out.putFields();
+      fields.put("rootURI", getLocalVFSContext().getRootURI());
+      fields.put("parent", parent);
+      fields.put("name", name);
+      fields.put("vfsUrl", vfsUrl);
+      out.writeFields();
+   }
+
+   private void readObject(ObjectInputStream in)
+      throws IOException, ClassNotFoundException
+   {
+      // Read in the serialPersistentFields
+      GetField fields = in.readFields();
+      URI rootURI = (URI) fields.get("rootURI", null);
+      this.parent = (VirtualFileHandler) fields.get("parent", null);
+      this.name = (String) fields.get("name", null);
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURI);
+      this.context = factory.getVFS(rootURI);
+      this.references = new AtomicInteger(0);
+      this.vfsUrl = (URL)fields.get("vfsUrl", null);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,208 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2006, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.virtual.plugins.context;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-
-import org.jboss.util.JBossObject;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * A delegating VirtualFileHandler that allows for overriding the delegate
- * parent and name. One usecase is a link which roots another VFSContext
- * under a different parent and name.
- * 
- * @author Scott.Stark at jboss.org
- * @version $Revision:$
- */
-public class DelegatingHandler extends AbstractVirtualFileHandler
-{
-   /** Serialization */
-   private static final long serialVersionUID = 1;
-   
-   /** The delegate */
-   private VirtualFileHandler delegate;
-
-   /**
-    * Create a DelegatingHandler without a delegate - which will have to be set afterwards
-    *
-    * @param context - the context for the parent
-    * @param parent - the parent of the delegate in this VFS
-    * @param name - the name of the delegate in this VFS
-    */
-   public DelegatingHandler(VFSContext context, VirtualFileHandler parent, String name)
-   {
-      this(context, parent, name, null);
-   }
-
-   /**
-    * Create a DelegatingHandler
-    * 
-    * @param context - the context for the parent
-    * @param parent - the parent of the delegate in this VFS
-    * @param name - the name of the delegate in this VFS
-    * @param delegate - the handler delegate
-    */
-   public DelegatingHandler(VFSContext context, VirtualFileHandler parent, String name, VirtualFileHandler delegate)
-   {
-      super(context, parent, name);
-      this.delegate = delegate;
-   }
-
-   public void setDelegate(VirtualFileHandler handler)
-   {
-      this.delegate = handler;
-   }
-
-   public VirtualFileHandler getDelegate()
-   {
-      if (delegate == null)
-         throw new IllegalArgumentException("Null delegate");
-      return delegate;
-   }
-
-   /**
-    * Set the vfs url.
-    *
-    * @param vfsUrl the vfs url
-    */
-   protected void setVfsUrl(URL vfsUrl)
-   {
-      if (delegate instanceof AbstractVirtualFileHandler)
-      {
-         ((AbstractVirtualFileHandler)delegate).setVfsUrl(vfsUrl);
-      }
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      VirtualFileHandler child = getDelegate().getChild(path);
-      if (getDelegate().equals(child))
-         return this;
-      else
-         return child;
-   }
-
-   public boolean removeChild(String path) throws IOException
-   {
-      throw new IOException("This method should never get called!");
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return getDelegate().getChildren(ignoreErrors);
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return getDelegate().getLastModified();
-   }
-
-   public long getSize() throws IOException
-   {
-      return getDelegate().getSize();
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      return getDelegate().isLeaf();
-   }
-
-   public boolean exists() throws IOException
-   {
-      return getDelegate().exists();
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      return getDelegate().isHidden();
-   }
-
-   public boolean isNested() throws IOException
-   {
-      return getDelegate().isNested();
-   }
-
-   public boolean delete(int gracePeriod) throws IOException
-   {
-      return getDelegate().delete(gracePeriod);
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      return getDelegate().openStream();
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return getDelegate().toURI();
-   }
-
-   public URL toURL() throws URISyntaxException, MalformedURLException
-   {
-      return getDelegate().toURL();
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      getDelegate().replaceChild(original, replacement);
-   }
-
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      return getDelegate().toVfsUrl();
-   }
-
-   public int hashCode()
-   {
-      if (delegate != null)
-         return delegate.hashCode();
-
-      return super.hashCode();
-   }
-
-   public boolean equals(Object o)
-   {
-      if (o == this)
-         return true;
-
-      if (o instanceof VirtualFileHandler == false)
-         return false;
-
-      VirtualFileHandler vfh = (VirtualFileHandler)o;
-      if (vfh instanceof DelegatingHandler)
-      {
-         DelegatingHandler handler = (DelegatingHandler) o;
-         vfh = handler.getDelegate();
-      }
-
-      return JBossObject.equals(delegate, vfh);
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,213 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.virtual.plugins.context;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.jboss.util.JBossObject;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * A delegating VirtualFileHandler that allows for overriding the delegate
+ * parent and name. One usecase is a link which roots another VFSContext
+ * under a different parent and name.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class DelegatingHandler extends AbstractVirtualFileHandler
+{
+   /** Serialization */
+   private static final long serialVersionUID = 1;
+   
+   /** The delegate */
+   private VirtualFileHandler delegate;
+
+   /**
+    * Create a DelegatingHandler without a delegate - which will have to be set afterwards
+    *
+    * @param context - the context for the parent
+    * @param parent - the parent of the delegate in this VFS
+    * @param name - the name of the delegate in this VFS
+    */
+   public DelegatingHandler(VFSContext context, VirtualFileHandler parent, String name)
+   {
+      this(context, parent, name, null);
+   }
+
+   /**
+    * Create a DelegatingHandler
+    * 
+    * @param context - the context for the parent
+    * @param parent - the parent of the delegate in this VFS
+    * @param name - the name of the delegate in this VFS
+    * @param delegate - the handler delegate
+    */
+   public DelegatingHandler(VFSContext context, VirtualFileHandler parent, String name, VirtualFileHandler delegate)
+   {
+      super(context, parent, name);
+      this.delegate = delegate;
+   }
+
+   public void setDelegate(VirtualFileHandler handler)
+   {
+      this.delegate = handler;
+   }
+
+   public VirtualFileHandler getDelegate()
+   {
+      if (delegate == null)
+         throw new IllegalArgumentException("Null delegate");
+      return delegate;
+   }
+
+   /**
+    * Set the vfs url.
+    *
+    * @param vfsUrl the vfs url
+    */
+   protected void setVfsUrl(URL vfsUrl)
+   {
+      if (delegate instanceof AbstractVirtualFileHandler)
+      {
+         ((AbstractVirtualFileHandler)delegate).setVfsUrl(vfsUrl);
+      }
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      VirtualFileHandler child = getDelegate().getChild(path);
+      if (getDelegate().equals(child))
+         return this;
+      else
+         return child;
+   }
+
+   public boolean removeChild(String path) throws IOException
+   {
+      throw new IOException("This method should never get called!");
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return getDelegate().getChildren(ignoreErrors);
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return getDelegate().getLastModified();
+   }
+
+   public long getSize() throws IOException
+   {
+      return getDelegate().getSize();
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      return getDelegate().isLeaf();
+   }
+
+   public boolean exists() throws IOException
+   {
+      return getDelegate().exists();
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return getDelegate().isHidden();
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return getDelegate().isNested();
+   }
+
+   public boolean delete(int gracePeriod) throws IOException
+   {
+      return getDelegate().delete(gracePeriod);
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      return getDelegate().openStream();
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return getDelegate().toURI();
+   }
+
+   public URL toURL() throws URISyntaxException, MalformedURLException
+   {
+      return getDelegate().toURL();
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      getDelegate().replaceChild(original, replacement);
+   }
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      return getDelegate().toVfsUrl();
+   }
+
+   public URL getRealURL() throws IOException, URISyntaxException
+   {
+      return getDelegate().getRealURL();
+   }
+
+   public int hashCode()
+   {
+      if (delegate != null)
+         return delegate.hashCode();
+
+      return super.hashCode();
+   }
+
+   public boolean equals(Object o)
+   {
+      if (o == this)
+         return true;
+
+      if (o instanceof VirtualFileHandler == false)
+         return false;
+
+      VirtualFileHandler vfh = (VirtualFileHandler)o;
+      if (vfh instanceof DelegatingHandler)
+      {
+         DelegatingHandler handler = (DelegatingHandler) o;
+         vfh = handler.getDelegate();
+      }
+
+      return JBossObject.equals(delegate, vfh);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,55 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Iterator;
-
-import org.jboss.util.file.ArchiveBrowser;
-import org.jboss.util.file.ArchiveBrowserFactory;
-import org.jboss.virtual.plugins.vfs.VirtualFileURLConnection;
-
-/**
- * This is a bridge to an older, crappier API written by myself.
- *
- * @deprecated
- *
- * @author <a href="bill at jboss.com">Bill Burke</a>
- * @version $Revision: 1.1 $
- */
-public class VfsArchiveBrowserFactory implements ArchiveBrowserFactory
-{
-   @SuppressWarnings("deprecation")
-   public Iterator create(URL url, ArchiveBrowser.Filter filter)
-   {
-      try
-      {
-         VirtualFileURLConnection conn = (VirtualFileURLConnection)url.openConnection();
-         return new VfsArchiveBrowser(filter, conn.getContent());
-      }
-      catch (IOException e)
-      {               
-         throw new RuntimeException("Unable to browse URL: " + url, e);
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/VfsArchiveBrowserFactory.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,59 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Iterator;
+
+import org.jboss.util.file.ArchiveBrowserFactory;
+import org.jboss.virtual.plugins.vfs.VirtualFileURLConnection;
+
+/**
+ * This is a bridge to an older, crappier API written by Bill.
+ *
+ * @deprecated
+ *
+ * @author <a href="bill at jboss.com">Bill Burke</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 1.1 $
+ */
+ at SuppressWarnings("deprecation")
+public class VfsArchiveBrowserFactory implements ArchiveBrowserFactory
+{
+   /** VFS archive browser instance */
+   public static final VfsArchiveBrowserFactory INSTANCE = new VfsArchiveBrowserFactory();
+
+   @SuppressWarnings("deprecation")
+   public Iterator create(URL url, org.jboss.util.file.ArchiveBrowser.Filter filter)
+   {
+      try
+      {
+         VirtualFileURLConnection conn = (VirtualFileURLConnection)url.openConnection();
+         return new VfsArchiveBrowser(filter, conn.getContent());
+      }
+      catch (IOException e)
+      {               
+         throw new RuntimeException("Unable to browse URL: " + url, e);
+      }
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,348 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context.file;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.util.file.Files;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.AbstractURLHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * FileHandler.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author Scott.Stark at jboss.org
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.1 $
- */
-public class FileHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
-{
-   private static final long serialVersionUID = 1;
-   /** The file */
-   private transient File file;
-   /** The child cache */
-   private transient Map<String, VirtualFileHandler> childCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
-
-   /**
-    * Create a new FileHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param file the file
-    * @param url the url
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url
-    */
-   public FileHandler(FileSystemContext context, VirtualFileHandler parent, File file, URL url) throws IOException
-   {
-      super(context, parent, url, file.getName());
-
-      this.file = file;
-      if (file.exists() == false)
-         throw new FileNotFoundException("File does not exist: " + file.getCanonicalPath());
-      setVfsUrl(new URL("vfs" + url));
-      // do cache here - on the file
-      cachedLastModified = getLastModified();
-   }
-   /**
-    * Create a new FileHandler
-    *  
-    * @param context the context
-    * @param parent the parent
-    * @param file the file
-    * @param uri the uri
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, uri
-    */
-   public FileHandler(FileSystemContext context, VirtualFileHandler parent, File file, URI uri) throws IOException
-   {
-      this(context, parent, file, uri.toURL());
-   }
-
-   protected void initCacheLastModified()
-   {
-      // ignore that url.openConnection.lastModified
-   }
-
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      if (getVfsUrl() == null)
-      {
-         setVfsUrl(new URL("vfs" + getURL()));
-      }
-      return getVfsUrl();
-   }
-
-   @Override
-   public FileSystemContext getVFSContext()
-   {
-      return (FileSystemContext) super.getVFSContext();
-   }
-   
-   /**
-    * Get the file for this file handler
-    * 
-    * @return the file
-    */
-   protected File getFile()
-   {
-      checkClosed();
-      return file;
-   }
-   
-   @Override
-   public long getLastModified()
-   {
-      return getFile().lastModified();
-   }
-
-   public boolean exists() throws IOException
-   {
-      return getFile().exists();
-   }
-
-   @Override
-   public long getSize()
-   {
-      return getFile().length();
-   }
-
-   public boolean isLeaf()
-   {
-      return getFile().isFile();
-   }
-
-   public boolean isHidden()
-   {
-      return getFile().isHidden();
-   }
-
-   public boolean isNested() throws IOException
-   {
-      return false;
-   }
-
-   public boolean delete(int gracePeriod) throws IOException
-   {
-      File f = getFile();
-
-      boolean exists = f.exists();
-      if (exists == false)
-         return false;
-
-      if (Files.delete(f) == false)
-      {
-         long endOfGrace = System.currentTimeMillis() + gracePeriod;
-         while(System.currentTimeMillis() < endOfGrace)
-         {
-            boolean done = Files.delete(f);
-            if (done)
-            {
-               childCache.remove(f.getName());
-               return true;
-            }
-            
-            try
-            {
-               Thread.sleep(100);
-            }
-            catch (InterruptedException e)
-            {
-               IOException ioe = new IOException("Interrupted: " + e);
-               ioe.initCause(e);
-               throw ioe;
-            }
-         }
-         return false;
-      }
-      else
-      {
-         childCache.remove(f.getName());
-         return true;
-      }
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      File parent = getFile();
-      File[] files = parent.listFiles();
-      if (files == null)
-         throw new IOException("Error listing files: " + parent.getCanonicalPath());
-      // We need to validate the files list due to jdk bug 6192331
-      List<File> tmpFiles = new ArrayList<File>();
-      for (File file : files)
-      {
-         if( file.canRead() == true )
-            tmpFiles.add(file);
-      }
-      if (tmpFiles.isEmpty())
-         return Collections.emptyList();
-
-      files = tmpFiles.toArray(new File[tmpFiles.size()]);
-      FileSystemContext context = getVFSContext();
-      
-      List<VirtualFileHandler> result = new ArrayList<VirtualFileHandler>();
-      Map<String, VirtualFileHandler> newCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
-      Map<String, VirtualFileHandler> oldCache = childCache;
-      // fill up a new cache with old entries
-      // old entries no longer existing in directory are purged by not being added to new cache
-      // we cache handlers so that things like JARs are recreated (optimization)
-      for (File file : files)
-      {
-         try
-         {
-            VirtualFileHandler handler;
-            handler = oldCache.get(file.getName());
-            // if underlying file has been modified then create a new handler instead of using the cached one
-            if (handler != null && handler.hasBeenModified())
-            {
-               handler = null;
-            }
-            if (handler == null)
-            {
-               handler = context.createVirtualFileHandler(this, file);
-            }
-            if (handler != null)
-            {
-               result.add(handler);
-               newCache.put(file.getName(), handler);
-            }
-         }
-         catch (IOException e)
-         {
-            if (ignoreErrors)
-               log.trace("Ignored: " + e);
-            else
-               throw e;
-         }
-      }
-      // cleanup old entries
-      childCache = newCache;
-      return result;
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      File parentFile = getFile();
-      File child = new File(parentFile, name);
-      VirtualFileHandler handler = childCache.get(name);
-      // if a child has already been created use that
-      // if the child has been modified on disk then create a new handler
-      if (handler != null && handler.hasBeenModified())
-      {
-         handler = null;
-      }
-      if (handler == null)
-      {
-         FileSystemContext context = getVFSContext();
-         handler = context.createVirtualFileHandler(this, child);
-         if (handler != null)
-            childCache.put(name, handler);
-      }
-      return handler;
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   /**
-    * Find an existing LinkHandler or create a new one.
-    *
-    * @param name a handler name
-    * @return cached or newly created LinkHandler
-    * @throws IOException for any error
-    */
-   LinkHandler getChildLink(String name) throws IOException
-   {
-      VirtualFileHandler handler = childCache.get(name);
-      if (handler == null)
-      {
-         // check if .vfslink.properties file exists for this name
-         File file = new File(getFile(), name + VFSUtils.VFS_LINK_PROPERTIES_SUFFIX);
-         if (file.isFile())
-         {
-            FileSystemContext ctx = getVFSContext();
-            return ctx.createLinkHandler(this, file, name);
-         }
-      }
-      else if (handler instanceof LinkHandler)
-      {
-         LinkHandler link = (LinkHandler) handler;
-         if (link.exists())
-         {
-            // detect any changes in configuration
-            FileSystemContext ctx = getVFSContext();
-            try
-            {
-               return ctx.createLinkHandler(this, new File(link.toURI()), name);
-            }
-            catch (URISyntaxException e)
-            {
-               IOException ex = new IOException("Failed to convert link to URI: " + link);
-               ex.initCause(e);
-               throw ex;
-            }
-         }
-         else
-         {
-            // remove from cache
-            childCache.remove(name);
-         }
-      }
-      return null;
-   }
-
-   public boolean removeChild(String name) throws IOException
-   {
-      return childCache.remove(name) != null;
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      childCache.put(original.getName(), replacement);
-   }
-
-   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
-   {
-      in.defaultReadObject();
-      // Initialize the transient values
-      this.file = new File(getURL().getPath());
-      this.childCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,353 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.file;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.util.file.Files;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractURLHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * FileHandler.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.1 $
+ */
+public class FileHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
+{
+   private static final long serialVersionUID = 1;
+   /** The file */
+   private transient File file;
+   /** The child cache */
+   private transient Map<String, VirtualFileHandler> childCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
+
+   /**
+    * Create a new FileHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param file the file
+    * @param url the url
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url
+    */
+   public FileHandler(FileSystemContext context, VirtualFileHandler parent, File file, URL url) throws IOException
+   {
+      super(context, parent, url, file.getName());
+
+      this.file = file;
+      if (file.exists() == false)
+         throw new FileNotFoundException("File does not exist: " + file.getCanonicalPath());
+      setVfsUrl(new URL("vfs" + url));
+      // do cache here - on the file
+      cachedLastModified = getLastModified();
+   }
+   /**
+    * Create a new FileHandler
+    *  
+    * @param context the context
+    * @param parent the parent
+    * @param file the file
+    * @param uri the uri
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, uri
+    */
+   public FileHandler(FileSystemContext context, VirtualFileHandler parent, File file, URI uri) throws IOException
+   {
+      this(context, parent, file, uri.toURL());
+   }
+
+   protected void initCacheLastModified()
+   {
+      // ignore that url.openConnection.lastModified
+   }
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      if (getVfsUrl() == null)
+      {
+         setVfsUrl(new URL("vfs" + getURL()));
+      }
+      return getVfsUrl();
+   }
+
+   public URL getRealURL() throws IOException, URISyntaxException
+   {
+      return getURL();
+   }
+
+   @Override
+   public FileSystemContext getVFSContext()
+   {
+      return (FileSystemContext) super.getVFSContext();
+   }
+   
+   /**
+    * Get the file for this file handler
+    * 
+    * @return the file
+    */
+   protected File getFile()
+   {
+      checkClosed();
+      return file;
+   }
+   
+   @Override
+   public long getLastModified()
+   {
+      return getFile().lastModified();
+   }
+
+   public boolean exists() throws IOException
+   {
+      return getFile().exists();
+   }
+
+   @Override
+   public long getSize()
+   {
+      return getFile().length();
+   }
+
+   public boolean isLeaf()
+   {
+      return getFile().isFile();
+   }
+
+   public boolean isHidden()
+   {
+      return getFile().isHidden();
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   public boolean delete(int gracePeriod) throws IOException
+   {
+      File f = getFile();
+
+      boolean exists = f.exists();
+      if (exists == false)
+         return false;
+
+      if (Files.delete(f) == false)
+      {
+         long endOfGrace = System.currentTimeMillis() + gracePeriod;
+         while(System.currentTimeMillis() < endOfGrace)
+         {
+            boolean done = Files.delete(f);
+            if (done)
+            {
+               childCache.remove(f.getName());
+               return true;
+            }
+            
+            try
+            {
+               Thread.sleep(100);
+            }
+            catch (InterruptedException e)
+            {
+               IOException ioe = new IOException("Interrupted: " + e);
+               ioe.initCause(e);
+               throw ioe;
+            }
+         }
+         return false;
+      }
+      else
+      {
+         childCache.remove(f.getName());
+         return true;
+      }
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      File parent = getFile();
+      File[] files = parent.listFiles();
+      if (files == null)
+         throw new IOException("Error listing files: " + parent.getCanonicalPath());
+      // We need to validate the files list due to jdk bug 6192331
+      List<File> tmpFiles = new ArrayList<File>();
+      for (File file : files)
+      {
+         if( file.canRead() == true )
+            tmpFiles.add(file);
+      }
+      if (tmpFiles.isEmpty())
+         return Collections.emptyList();
+
+      files = tmpFiles.toArray(new File[tmpFiles.size()]);
+      FileSystemContext context = getVFSContext();
+      
+      List<VirtualFileHandler> result = new ArrayList<VirtualFileHandler>();
+      Map<String, VirtualFileHandler> newCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
+      Map<String, VirtualFileHandler> oldCache = childCache;
+      // fill up a new cache with old entries
+      // old entries no longer existing in directory are purged by not being added to new cache
+      // we cache handlers so that things like JARs are recreated (optimization)
+      for (File file : files)
+      {
+         try
+         {
+            VirtualFileHandler handler;
+            handler = oldCache.get(file.getName());
+            // if underlying file has been modified then create a new handler instead of using the cached one
+            if (handler != null && handler.hasBeenModified())
+            {
+               handler = null;
+            }
+            if (handler == null)
+            {
+               handler = context.createVirtualFileHandler(this, file);
+            }
+            if (handler != null)
+            {
+               result.add(handler);
+               newCache.put(file.getName(), handler);
+            }
+         }
+         catch (IOException e)
+         {
+            if (ignoreErrors)
+               log.trace("Ignored: " + e);
+            else
+               throw e;
+         }
+      }
+      // cleanup old entries
+      childCache = newCache;
+      return result;
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      File parentFile = getFile();
+      File child = new File(parentFile, name);
+      VirtualFileHandler handler = childCache.get(name);
+      // if a child has already been created use that
+      // if the child has been modified on disk then create a new handler
+      if (handler != null && handler.hasBeenModified())
+      {
+         handler = null;
+      }
+      if (handler == null)
+      {
+         FileSystemContext context = getVFSContext();
+         handler = context.createVirtualFileHandler(this, child);
+         if (handler != null)
+            childCache.put(name, handler);
+      }
+      return handler;
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   /**
+    * Find an existing LinkHandler or create a new one.
+    *
+    * @param name a handler name
+    * @return cached or newly created LinkHandler
+    * @throws IOException for any error
+    */
+   LinkHandler getChildLink(String name) throws IOException
+   {
+      VirtualFileHandler handler = childCache.get(name);
+      if (handler == null)
+      {
+         // check if .vfslink.properties file exists for this name
+         File file = new File(getFile(), name + VFSUtils.VFS_LINK_PROPERTIES_SUFFIX);
+         if (file.isFile())
+         {
+            FileSystemContext ctx = getVFSContext();
+            return ctx.createLinkHandler(this, file, name);
+         }
+      }
+      else if (handler instanceof LinkHandler)
+      {
+         LinkHandler link = (LinkHandler) handler;
+         if (link.exists())
+         {
+            // detect any changes in configuration
+            FileSystemContext ctx = getVFSContext();
+            try
+            {
+               return ctx.createLinkHandler(this, new File(link.toURI()), name);
+            }
+            catch (URISyntaxException e)
+            {
+               IOException ex = new IOException("Failed to convert link to URI: " + link);
+               ex.initCause(e);
+               throw ex;
+            }
+         }
+         else
+         {
+            // remove from cache
+            childCache.remove(name);
+         }
+      }
+      return null;
+   }
+
+   public boolean removeChild(String name) throws IOException
+   {
+      return childCache.remove(name) != null;
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      childCache.put(original.getName(), replacement);
+   }
+
+   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+   {
+      in.defaultReadObject();
+      // Initialize the transient values
+      this.file = new File(getURL().getPath());
+      this.childCache = Collections.synchronizedMap(new HashMap<String, VirtualFileHandler>());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,433 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context.file;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.List;
-import java.util.Properties;
-
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.plugins.context.AbstractVFSContext;
-import org.jboss.virtual.plugins.context.DelegatingHandler;
-import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
-import org.jboss.virtual.plugins.context.jar.JarHandler;
-import org.jboss.virtual.plugins.context.jar.JarUtils;
-import org.jboss.virtual.spi.LinkInfo;
-import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.logging.Logger;
-
-/**
- * FileSystemContext.
- *
- * Jar archives are processed through {@link org.jboss.virtual.plugins.context.zip.ZipEntryContext}.
- *
- * To switch back to {@link org.jboss.virtual.plugins.context.jar.JarHandler}
- * set a system property <em>jboss.vfs.forceVfsJar=true</em>
- *
- * Explicit case sensitive path checking can be turned on by adding an option parameter
- * <em>?caseSensitive=true<em> to context URL. This may be desired when native filesystem is not
- * case sensitive (i.e. if running on Windows).
- *
- * Case sesitivity can be turned on for all context URLs by setting system property
- * <em>jboss.vfs.forceCaseSensitive=true</em>.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.1 $
- */
-public class FileSystemContext extends AbstractVFSContext
-{
-   private static final Logger log = Logger.getLogger(FileSystemContext.class);
-
-   /** true if forcing fallback to vfsjar from default vfszip */
-   private static boolean forceVfsJar;
-
-   /** true if case sensitivity should be enforced */
-   private static boolean forceCaseSensitive;
-
-   static
-   {
-      forceVfsJar = AccessController.doPrivileged(new CheckForceVfsJar());
-
-      if (forceVfsJar)
-         log.info("VFS forced fallback to vfsjar is enabled.");
-
-      forceCaseSensitive = AccessController.doPrivileged(new CheckForceCaseSensitive());
-
-      if (forceCaseSensitive)
-         log.debug("VFS forced case sensitivity is enabled.");
-   }
-
-   /** The root file */
-   private final VirtualFileHandler root;
-   
-   /** A reference to the virtual file of the root to stop it getting closed */
-   private final VirtualFile rootFile;
-   
-   /**
-    * Get the file for a url
-    * 
-    * @param uri the url
-    * @return the file
-    * @throws IOException for any error accessing the file system
-    * @throws URISyntaxException if cannot create URI 
-    * @throws IllegalArgumentException for a null url
-    */
-   private static File getFile(URI uri) throws IOException, URISyntaxException
-   {
-      if (uri == null)
-         throw new IllegalArgumentException("Null uri");
-      // This ctor will not accept uris with authority, fragment or query
-      if(uri.getAuthority() != null || uri.getFragment() != null || uri.getQuery() != null)
-         uri = new URI("file", null, uri.getPath(), null);
-      return new File(uri);
-   }
-
-   /**
-    * Get the url for a file
-    * 
-    * @param file the file
-    * @return the url
-    * @throws IOException for any error accessing the file system
-    * @throws IllegalArgumentException for a null file
-    */
-   private static URI getFileURI(File file) throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-
-      URI url = file.toURI();
-      String path = url.getPath();
-      if (file.isDirectory() == false)
-      {
-         path = VFSUtils.fixName(path);
-      }
-      else if (path.endsWith("/") == false)
-      {
-            path = path + '/';
-      }
-
-      try
-      {
-         return new URI("file", null, path, null);
-      }
-      catch(URISyntaxException e)
-      {
-         // Should not be possible
-         throw new IllegalStateException("Failed to convert file.toURI", e);
-      }
-   }
-   
-   /**
-    * Create a new FileSystemContext.
-    * 
-    * @param rootURL the root url
-    * @throws IOException for an error accessing the file system
-    * @throws URISyntaxException for an error parsing the uri
-    */
-   public FileSystemContext(URL rootURL) throws IOException, URISyntaxException
-   {
-      this(VFSUtils.toURI(rootURL));
-   }
-
-   /**
-    * Create a new FileSystemContext.
-    * 
-    * @param rootURI the root uri
-    * @throws IOException for an error accessing the file system
-    * @throws URISyntaxException if cannot create URI
-    */
-   public FileSystemContext(URI rootURI) throws IOException, URISyntaxException
-   {
-      this(rootURI, getFile(rootURI));
-   }
-   
-   /**
-    * Create a new FileSystemContext.
-    * 
-    * @param file the root file
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null file
-    * @throws URISyntaxException for an error parsing the uri
-    */
-   public FileSystemContext(File file) throws IOException, URISyntaxException
-   {
-      this(getFileURI(file), file);
-   }
-
-   /**
-    * Create a new FileSystemContext.
-    * 
-    * @param rootURI the root uri
-    * @param file the file
-    * @throws IOException for an error accessing the file system
-    */
-   private FileSystemContext(URI rootURI, File file) throws IOException
-   {
-      super(rootURI);
-      root = createVirtualFileHandler(null, file);
-      if (root == null)
-         throw new java.io.FileNotFoundException((file == null ? "null" : file.getName())
-                 + " doesn't exist. (rootURI: " + rootURI + ", file: " + file + ")");
-
-      rootFile = root.getVirtualFile();
-   }
-
-   public String getName()
-   {
-      return root.getName();
-   }
-
-   public VirtualFileHandler getRoot() throws IOException
-   {
-      return root;
-   }
-
-   /**
-    * Create a new virtual file handler
-    * 
-    * @param parent the parent
-    * @param file the file
-    * @return the handler
-    * @throws IOException for any error accessing the file system
-    * @throws IllegalArgumentException for a null file
-    */
-   public VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, File file) throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      
-      String name = file.getName();
-      if (file.isFile() && JarUtils.isArchive(name))
-      {
-         if (exists(file) == false)
-            return null;
-
-         if (forceVfsJar)
-         {
-            try
-            {
-               return new JarHandler(this, parent, file, file.toURL(), name);
-            }
-            catch(IOException e)
-            {
-               log.debug("Exception while trying to handle file (" + name + ") as a jar: " + e.getMessage());
-            }
-         }
-         else
-         {
-            try
-            {
-               return mountZipFS(parent, name, file);
-            }
-            catch (Exception e)
-            {
-               log.debug("IGNORING: Exception while trying to handle file (" + name + ") as a jar through ZipEntryContext: ", e);
-            }
-         }
-      }
-      return createVirtualFileHandler(parent, file, getFileURI(file));
-   }
-
-   /**
-    * Create zip file system.
-    *
-    * @param parent the parent
-    * @param name the name
-    * @param file the file
-    * @return new zip fs delegating handler
-    * @throws IOException for any error
-    * @throws URISyntaxException for any URI syntax error
-    */
-   protected DelegatingHandler mountZipFS(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
-   {
-      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
-      URL fileUrl = file.toURL();
-      URL delegatorUrl = fileUrl;
-
-      if (parent != null)
-         delegatorUrl = getChildURL(parent, name);
-
-      delegatorUrl = setOptionsToURL(delegatorUrl);
-      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl);
-
-      VirtualFileHandler handler = ctx.getRoot();
-      delegator.setDelegate(handler);
-
-      return delegator;
-   }
-
-   /**
-    * Create a new virtual file handler
-    * 
-    * @param parent the parent
-    * @param file the file
-    * @param uri the uri
-    * @return the handler
-    * @throws IOException for any error accessing the file system
-    * @throws IllegalArgumentException for a null file
-    */
-   public VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, File file, URI uri)
-      throws IOException
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      if (uri == null)
-         throw new IllegalArgumentException("Null uri");
-
-      VirtualFileHandler handler = null;
-      if( VFSUtils.isLink(file.getName()) )
-      {
-         handler = createLinkHandler(parent, file, null);
-      }
-      else if (exists(file) == false && parent != null)
-      {
-         // See if we can resolve this to a link in the parent
-         if (parent instanceof FileHandler)
-            handler = ((FileHandler) parent).getChildLink(file.getName());
-      }
-      else if (exists(file))
-      {
-         handler = new FileHandler(this, parent, file, uri);
-      }
-      return handler;
-   }
-
-   /**
-    * Create a new <tt>LinkHandler</tt> from .vfslink.properties file.
-    * A link name is derived from file name by cutting off .vfslink.properties suffix
-    *
-    * @param parent the parent handler
-    * @param file .vfslink.properties file
-    * @param linkNameCondition condition - if not null new LinkHandler will only be created if link name
-    *                            extracted from the file name matches linkNameCondition
-    * @return newly created <tt>LinkHandler</tt>
-    * @throws IOException for any error
-    */
-   LinkHandler createLinkHandler(VirtualFileHandler parent, File file, String linkNameCondition)
-        throws IOException
-   {
-      URI uri = file.toURI();
-      LinkHandler handler = null;
-
-      Properties props = new Properties();
-      FileInputStream fis = new FileInputStream(file);
-      try
-      {
-         List<LinkInfo> links = VFSUtils.readLinkInfo(fis, file.getName(), props);
-         String name = file.getName();
-         name = name.substring(0, name.indexOf(VFSUtils.VFS_LINK_INFIX));
-         if (name.length() == 0 || ".".equals(name) || "..".equals(name))
-            throw new IOException("Invalid link name: " + name + " (generated from file: " + file + ")");
-         if (linkNameCondition == null || linkNameCondition.equals(name))
-            handler = new LinkHandler(this, parent, uri, name, links);
-      }
-      catch(URISyntaxException e)
-      {
-         IOException ex = new IOException("Failed to parse link URIs");
-         ex.initCause(e);
-         throw ex;
-      }
-      finally
-      {
-         try
-         {
-            fis.close();
-         }
-         catch(IOException e)
-         {
-            log.debug("Exception closing file input stream: " + fis, e);
-         }
-      }
-      return handler;
-   }
-
-   /**
-    * Tests if file exists taking case sensitivity into account - if it's enabled
-    *
-    * @param file file to check
-    * @return true if file exists
-    * @throws IOException for any error
-    */
-   protected boolean exists(File file) throws IOException
-   {
-      // if force case sensitive is enabled - extra check is required
-      boolean isCaseSensitive = forceCaseSensitive;
-      if (isCaseSensitive == false)
-      {
-         String flag = getOptions().get(VFSUtils.CASE_SENSITIVE_QUERY);
-         isCaseSensitive = Boolean.valueOf(flag);
-      }
-
-      if (isCaseSensitive && file.getCanonicalFile().getName().equals(file.getName()) == false)
-         return false;
-
-      return file.exists();
-   }
-
-   /**
-    * Is forceCaseSensitive enabled
-    *
-    * Only relevant for native filesystems
-    * that are not case sensitive
-    *
-    * @return true if case sensitivity is enabled
-    */
-   public boolean isForcedCaseSensitive() {
-      return forceCaseSensitive;
-   }
-
-   @Override
-   protected void finalize() throws Throwable
-   {
-      if (rootFile != null)
-         rootFile.close();
-      super.finalize();
-   }
-
-   private static class CheckForceVfsJar implements PrivilegedAction<Boolean>
-   {
-      public Boolean run()
-      {
-         String forceString = System.getProperty(VFSUtils.FORCE_VFS_JAR_KEY, "false");
-         return Boolean.valueOf(forceString);
-      }
-   }
-
-   private static class CheckForceCaseSensitive implements PrivilegedAction<Boolean>
-   {
-      public Boolean run()
-      {
-         String forceString = System.getProperty(VFSUtils.FORCE_CASE_SENSITIVE_KEY, "false");
-         return Boolean.valueOf(forceString);
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,441 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+import java.util.Properties;
+
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.AbstractVFSContext;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.plugins.context.jar.JarHandler;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.spi.LinkInfo;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.logging.Logger;
+
+/**
+ * FileSystemContext.
+ *
+ * Jar archives are processed through {@link org.jboss.virtual.plugins.context.zip.ZipEntryContext}.
+ *
+ * To switch back to {@link org.jboss.virtual.plugins.context.jar.JarHandler}
+ * set a system property <em>jboss.vfs.forceVfsJar=true</em>
+ *
+ * Explicit case sensitive path checking can be turned on by adding an option parameter
+ * <em>?caseSensitive=true<em> to context URL. This may be desired when native filesystem is not
+ * case sensitive (i.e. if running on Windows).
+ *
+ * Case sesitivity can be turned on for all context URLs by setting system property
+ * <em>jboss.vfs.forceCaseSensitive=true</em>.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.1 $
+ */
+public class FileSystemContext extends AbstractVFSContext
+{
+   private static final Logger log = Logger.getLogger(FileSystemContext.class);
+
+   /** true if forcing fallback to vfsjar from default vfszip */
+   private static boolean forceVfsJar;
+
+   /** true if case sensitivity should be enforced */
+   private static boolean forceCaseSensitive;
+
+   static
+   {
+      forceVfsJar = AccessController.doPrivileged(new CheckForceVfsJar());
+
+      if (forceVfsJar)
+         log.info("VFS forced fallback to vfsjar is enabled.");
+
+      forceCaseSensitive = AccessController.doPrivileged(new CheckForceCaseSensitive());
+
+      if (forceCaseSensitive)
+         log.debug("VFS forced case sensitivity is enabled.");
+   }
+
+   /** The temp file */
+   private transient File file;
+
+   /** The root file */
+   private VirtualFileHandler root;
+   
+   /** A reference to the virtual file of the root to stop it getting closed */
+   private VirtualFile rootFile;
+   
+   /**
+    * Get the file for a url
+    * 
+    * @param uri the url
+    * @return the file
+    * @throws IOException for any error accessing the file system
+    * @throws URISyntaxException if cannot create URI 
+    * @throws IllegalArgumentException for a null url
+    */
+   private static File getFile(URI uri) throws IOException, URISyntaxException
+   {
+      if (uri == null)
+         throw new IllegalArgumentException("Null uri");
+      // This ctor will not accept uris with authority, fragment or query
+      if(uri.getAuthority() != null || uri.getFragment() != null || uri.getQuery() != null)
+         uri = new URI("file", null, uri.getPath(), null);
+      return new File(uri);
+   }
+
+   /**
+    * Get the url for a file
+    * 
+    * @param file the file
+    * @return the url
+    * @throws IOException for any error accessing the file system
+    * @throws IllegalArgumentException for a null file
+    */
+   private static URI getFileURI(File file) throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+
+      URI url = file.toURI();
+      String path = url.getPath();
+      if (file.isDirectory() == false)
+      {
+         path = VFSUtils.fixName(path);
+      }
+      else if (path.endsWith("/") == false)
+      {
+            path = path + '/';
+      }
+
+      try
+      {
+         return new URI("file", null, path, null);
+      }
+      catch(URISyntaxException e)
+      {
+         // Should not be possible
+         throw new IllegalStateException("Failed to convert file.toURI", e);
+      }
+   }
+   
+   /**
+    * Create a new FileSystemContext.
+    * 
+    * @param rootURL the root url
+    * @throws IOException for an error accessing the file system
+    * @throws URISyntaxException for an error parsing the uri
+    */
+   public FileSystemContext(URL rootURL) throws IOException, URISyntaxException
+   {
+      this(VFSUtils.toURI(rootURL));
+   }
+
+   /**
+    * Create a new FileSystemContext.
+    * 
+    * @param rootURI the root uri
+    * @throws IOException for an error accessing the file system
+    * @throws URISyntaxException if cannot create URI
+    */
+   public FileSystemContext(URI rootURI) throws IOException, URISyntaxException
+   {
+      this(rootURI, getFile(rootURI));
+   }
+   
+   /**
+    * Create a new FileSystemContext.
+    * 
+    * @param file the root file
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null file
+    * @throws URISyntaxException for an error parsing the uri
+    */
+   public FileSystemContext(File file) throws IOException, URISyntaxException
+   {
+      this(getFileURI(file), file);
+   }
+
+   /**
+    * Create a new FileSystemContext.
+    * 
+    * @param rootURI the root uri
+    * @param file the file
+    * @throws IOException for an error accessing the file system
+    */
+   private FileSystemContext(URI rootURI, File file) throws IOException
+   {
+      super(rootURI);
+      this.file = file;
+   }
+
+   public String getName()
+   {
+      return (root != null) ? root.getName() : file.getName();
+   }
+
+   public VirtualFileHandler getRoot() throws IOException
+   {
+      if (root == null)
+      {
+         root = createVirtualFileHandler(null, file);
+         if (root == null)
+            throw new java.io.FileNotFoundException((file == null ? "<null>" : file.getName())
+                    + " doesn't exist. (rootURI: " + getRootURI() + ", file: " + file + ")");
+
+         rootFile = root.getVirtualFile();
+         file = null; // nullify temp file
+      }
+      return root;
+   }
+
+   /**
+    * Create a new virtual file handler
+    * 
+    * @param parent the parent
+    * @param file the file
+    * @return the handler
+    * @throws IOException for any error accessing the file system
+    * @throws IllegalArgumentException for a null file
+    */
+   public VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, File file) throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      
+      String name = file.getName();
+      if (file.isFile() && JarUtils.isArchive(name))
+      {
+         if (exists(file) == false)
+            return null;
+
+         if (forceVfsJar)
+         {
+            try
+            {
+               return new JarHandler(this, parent, file, file.toURL(), name);
+            }
+            catch(IOException e)
+            {
+               log.debug("Exception while trying to handle file (" + name + ") as a jar: " + e.getMessage());
+            }
+         }
+         else
+         {
+            try
+            {
+               return mountZipFS(parent, name, file);
+            }
+            catch (Exception e)
+            {
+               log.debug("IGNORING: Exception while trying to handle file (" + name + ") as a jar through ZipEntryContext: ", e);
+            }
+         }
+      }
+      return createVirtualFileHandler(parent, file, getFileURI(file));
+   }
+
+   /**
+    * Create zip file system.
+    *
+    * @param parent the parent
+    * @param name the name
+    * @param file the file
+    * @return new zip fs delegating handler
+    * @throws IOException for any error
+    * @throws URISyntaxException for any URI syntax error
+    */
+   protected DelegatingHandler mountZipFS(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
+   {
+      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+      URL fileUrl = file.toURL();
+      URL delegatorUrl = fileUrl;
+
+      if (parent != null)
+         delegatorUrl = getChildURL(parent, name);
+
+      delegatorUrl = setOptionsToURL(delegatorUrl);
+      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl);
+
+      VirtualFileHandler handler = ctx.getRoot();
+      delegator.setDelegate(handler);
+
+      return delegator;
+   }
+
+   /**
+    * Create a new virtual file handler
+    * 
+    * @param parent the parent
+    * @param file the file
+    * @param uri the uri
+    * @return the handler
+    * @throws IOException for any error accessing the file system
+    * @throws IllegalArgumentException for a null file
+    */
+   public VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, File file, URI uri)
+      throws IOException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      if (uri == null)
+         throw new IllegalArgumentException("Null uri");
+
+      VirtualFileHandler handler = null;
+      if(VFSUtils.isLink(file.getName()))
+      {
+         handler = createLinkHandler(parent, file, null);
+      }
+      else if (exists(file) == false && parent != null)
+      {
+         // See if we can resolve this to a link in the parent
+         if (parent instanceof FileHandler)
+            handler = ((FileHandler) parent).getChildLink(file.getName());
+      }
+      else if (exists(file))
+      {
+         handler = new FileHandler(this, parent, file, uri);
+      }
+      return handler;
+   }
+
+   /**
+    * Create a new <tt>LinkHandler</tt> from .vfslink.properties file.
+    * A link name is derived from file name by cutting off .vfslink.properties suffix
+    *
+    * @param parent the parent handler
+    * @param file .vfslink.properties file
+    * @param linkNameCondition condition - if not null new LinkHandler will only be created if link name
+    *                            extracted from the file name matches linkNameCondition
+    * @return newly created <tt>LinkHandler</tt>
+    * @throws IOException for any error
+    */
+   LinkHandler createLinkHandler(VirtualFileHandler parent, File file, String linkNameCondition)
+        throws IOException
+   {
+      URI uri = file.toURI();
+      LinkHandler handler = null;
+
+      Properties props = new Properties();
+      FileInputStream fis = new FileInputStream(file);
+      try
+      {
+         List<LinkInfo> links = VFSUtils.readLinkInfo(fis, file.getName(), props);
+         String name = file.getName();
+         name = name.substring(0, name.indexOf(VFSUtils.VFS_LINK_INFIX));
+         if (name.length() == 0 || ".".equals(name) || "..".equals(name))
+            throw new IOException("Invalid link name: " + name + " (generated from file: " + file + ")");
+         if (linkNameCondition == null || linkNameCondition.equals(name))
+            handler = new LinkHandler(this, parent, uri, name, links);
+      }
+      catch(URISyntaxException e)
+      {
+         IOException ex = new IOException("Failed to parse link URIs");
+         ex.initCause(e);
+         throw ex;
+      }
+      finally
+      {
+         try
+         {
+            fis.close();
+         }
+         catch(IOException e)
+         {
+            log.debug("Exception closing file input stream: " + fis, e);
+         }
+      }
+      return handler;
+   }
+
+   /**
+    * Tests if file exists taking case sensitivity into account - if it's enabled
+    *
+    * @param file file to check
+    * @return true if file exists
+    * @throws IOException for any error
+    */
+   protected boolean exists(File file) throws IOException
+   {
+      // if force case sensitive is enabled - extra check is required
+      boolean isCaseSensitive = forceCaseSensitive;
+      if (isCaseSensitive == false)
+      {
+         String flag = getOptions().get(VFSUtils.CASE_SENSITIVE_QUERY);
+         isCaseSensitive = Boolean.valueOf(flag);
+      }
+
+      if (isCaseSensitive && file.getCanonicalFile().getName().equals(file.getName()) == false)
+         return false;
+
+      return file.exists();
+   }
+
+   /**
+    * Is forceCaseSensitive enabled
+    *
+    * Only relevant for native filesystems
+    * that are not case sensitive
+    *
+    * @return true if case sensitivity is enabled
+    */
+   public boolean isForcedCaseSensitive() {
+      return forceCaseSensitive;
+   }
+
+   @Override
+   protected void finalize() throws Throwable
+   {
+      if (rootFile != null)
+         rootFile.close();
+      super.finalize();
+   }
+
+   private static class CheckForceVfsJar implements PrivilegedAction<Boolean>
+   {
+      public Boolean run()
+      {
+         String forceString = System.getProperty(VFSUtils.FORCE_VFS_JAR_KEY, "false");
+         return Boolean.valueOf(forceString);
+      }
+   }
+
+   private static class CheckForceCaseSensitive implements PrivilegedAction<Boolean>
+   {
+      public Boolean run()
+      {
+         String forceString = System.getProperty(VFSUtils.FORCE_CASE_SENSITIVE_KEY, "false");
+         return Boolean.valueOf(forceString);
+      }
+   }
+}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/helpers (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/helpers)

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,1214 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context.zip;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.AbstractVFSContext;
-import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.plugins.context.DelegatingHandler;
-import org.jboss.virtual.plugins.context.jar.JarUtils;
-import org.jboss.virtual.plugins.copy.AbstractCopyMechanism;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * <tt>ZipEntryContext</tt> implements a {@link org.jboss.virtual.spi.VFSContext}
- * that exposes a zip archive as a virtual file system.
- *
- * Zip archive can be in a form of a file or a stream.
- *
- * Nested archives are processed through this same class.
- * By default nested archives are cached in memory and mounted as new
- * instances of <tt>ZipEntryContext</tt> with <tt>ZipStreamWrapper</tt> as a source.
- * If system property <em>jboss.vfs.forceCopy=true</em> is specified,
- * or URL query parameter <em>forceCopy=true</em> is present,
- * nested archives are extracted into a temp directory before being
- * mounted as new instances of <tt>ZipEntryContext</tt>.
- *
- * In-memory nested archives may consume a lot of memory. To reduce memory footprint
- * at the expense of performance, system property <em>jboss.vfs.optimizeForMemory=true<em>
- * can be set.
- *
- * This context implementation has two modes of releasing file locks.
- * <em>Asynchronous</em> mode is the default one since it is better performant.
- * To switch this to <em>synchronous</em> mode a system property
- * <em>jboss.vfs.forceNoReaper=true</em> can be specified or URL query parameter
- * <em>noReaper=true</em> can be included in context URL.
- *
- * This context implementation is a replacement for
- * {@link org.jboss.virtual.plugins.context.jar.JarContext}.
- *
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.0 $
- */
-public class ZipEntryContext extends AbstractVFSContext
-{
-   /** Logger */
-   private static final Logger log = Logger.getLogger(ZipEntryContext.class);
-
-   /** Global setting for nested archive processing mode: copy or no-copy (default) */
-   private static boolean forceCopy;
-
-   static
-   {
-      deleteTmpDirContents();
-
-      forceCopy = AccessController.doPrivileged(new CheckForceCopy());
-
-      if (forceCopy)
-         log.info("VFS force nested jars copy-mode is enabled.");
-   }
-
-   /** Abstracted access to zip archive - either ZipFileWrapper or ZipStreamWrapper */
-   private ZipWrapper zipSource;
-
-   /** Entry path representing a context root - archive root is not necessarily a context root */
-   private String rootEntryPath = "";
-
-   /** AutoClean signals if zip archive should be deleted after closing the context - true for nested archives */
-   private boolean autoClean = false;
-
-   /** Registry of everything that zipSource contains */
-   private Map<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
-
-   /** Have zip entries been navigated yet */
-   private InitializationStatus initStatus = InitializationStatus.NOT_INITIALIZED;
-
-   /**
-    * Create a new ZipEntryContext
-    *
-    * @param rootURL - file or jar:file url
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   public ZipEntryContext(URL rootURL) throws URISyntaxException, IOException
-   {
-      this(rootURL, false);
-   }
-
-   /**
-    * Create a new ZipEntryContext
-    *
-    * @param rootURL - file or jar:file url
-    * @param autoClean - true if file represented by rootURL should be deleted after this context is closed
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   public ZipEntryContext(URL rootURL, boolean autoClean) throws URISyntaxException, IOException
-   {
-      super(VFSUtils.toURI(fixUrl(rootURL)));
-      this.autoClean = autoClean;
-      init(rootURL, null, null);
-   }
-
-   /**
-    * Create a new ZipEntryContext to be mounted into another context
-    *
-    * @param rootURL - url representing this context within another context
-    * @param peer - file handler in another context through which this context is being mounted
-    * @param localRootUrl - file or jar:file url
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl) throws URISyntaxException, IOException
-   {
-      this(rootURL, peer, localRootUrl, false);
-   }
-
-   /**
-    * Create a new ZipEntryContext to be mounted into another context
-    *
-    * @param rootURL - url representing this context within another context
-    * @param peer - file handler in another context through which this context is being mounted
-    * @param localRootUrl - file or jar:file url
-    * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl, boolean autoClean) throws URISyntaxException, IOException
-   {
-      super(VFSUtils.toURI(fixUrl(rootURL)));
-      this.autoClean = autoClean;
-      init(localRootUrl, peer, null);
-   }
-
-   /**
-    * Create a new ZipEntryContext to be mounted into another context
-    *
-    * @param rootURL - url representing this context within another context
-    * @param peer - file handler in another context through which this context is being mounted
-    * @param zipWrapper - abstracted zip archive source
-    * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, ZipWrapper zipWrapper, boolean autoClean) throws URISyntaxException, IOException
-   {
-      super(VFSUtils.toURI(fixUrl(rootURL)));
-      this.autoClean = autoClean;
-      init(null, peer, zipWrapper);
-   }
-
-   /**
-    * Extra initialization in addition to what's inside constructors
-    *
-    * @param localRootURL the local url
-    * @param peer the peer
-    * @param zipWrapper zip wrapper
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   private void init(URL localRootURL, VirtualFileHandler peer, ZipWrapper zipWrapper) throws IOException, URISyntaxException
-   {
-      if (zipWrapper == null)
-      {
-         if (localRootURL == null)
-            throw new IllegalArgumentException("No ZipWrapper specified and localRootURL is null");
-
-         // initialize rootEntryPath and get archive file path
-         String rootPath = initRootAndPath(localRootURL);
-         zipSource = createZipSource(rootPath);
-      }
-      else
-      {
-         zipSource = zipWrapper;
-      }
-      
-      setRootPeer(peer);
-      String name = getRootURI().getPath();
-      int toPos = name.length();
-
-      // cut off any ending slash
-      if(name.length() != 0 && name.charAt(name.length()-1) == '/')
-         toPos --;
-
-      // name is last path component
-      int namePos = name.lastIndexOf("/", toPos-1);
-      name = name.substring(namePos+1, toPos);
-      
-      // cut off any ending exclamation
-      if(name.length() != 0 && name.charAt(name.length()-1) == '!')
-         name = name.substring(0, name.length()-1);
-
-      // init initial root EntryInfo that will be overwritten
-      // if zip entry exists for rootEntryPath
-      entries.put("", new EntryInfo(new ZipEntryHandler(this, null, name, true), null));
-
-      // It's lazy init now
-      //initEntries();
-   }
-
-   /**
-    * Create zip source.
-    *
-    * @param rootPath the root path
-    * @return zip entry wrapper
-    * @throws IOException for any error
-    */
-   protected ZipWrapper createZipSource(String rootPath) throws IOException
-   {
-      File file = null;
-      String relative = null;
-      File fp = new File(rootPath);
-      if (fp.exists())
-      {
-         file = fp;
-      }
-      else
-      {
-         File curr = fp;
-         relative = fp.getName();
-         while ((curr = curr.getParentFile()) != null)
-         {
-            if (curr.exists())
-            {
-               file = curr;
-               break;
-            }
-            else
-            {
-               relative = curr.getName() + "/" + relative;
-            }
-         }
-      }
-
-      if (file == null)
-         throw new IOException("VFS file does not exist: " + rootPath);
-
-      if (relative != null)
-      {
-         return findEntry(new FileInputStream(file), relative);
-      }
-      else
-      {
-         boolean noReaper = Boolean.valueOf(getOptions().get(VFSUtils.NO_REAPER_QUERY));
-         return new ZipFileWrapper(file, autoClean, noReaper);
-      }
-   }
-
-   /**
-    * Find exact entry.
-    * Use recursion on relative path.
-    *
-    * @param is the input stream
-    * @param relative relative path
-    * @return zip wrapper instance
-    * @throws IOException for any error
-    */
-   protected ZipWrapper findEntry(InputStream is, String relative) throws IOException
-   {
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      VFSUtils.copyStreamAndClose(is, baos);
-      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
-
-      // first we need to find best/longest name
-      ZipInputStream zis = new ZipInputStream(bais);
-      ZipEntry entry;
-      String longestNameMatch = null;
-      while((entry = zis.getNextEntry()) != null)
-      {
-         String entryName = entry.getName();
-         String match = entryName;
-         if (entry.isDirectory())
-            match = match.substring(0, match.length() - 1);
-
-         if (relative.startsWith(match))
-         {
-            if (match.equals(relative))
-            {
-               if (entry.isDirectory())
-               {
-                  this.rootEntryPath = relative;
-                  return new ZipDirWrapper(zis, entryName, System.currentTimeMillis(), bais);
-               }
-               else if (JarUtils.isArchive(match) == false)
-               {
-                  return new ZipEntryWrapper(zis, entryName, System.currentTimeMillis());
-               }
-               else
-               {
-                  return new ZipStreamWrapper(zis, entryName, System.currentTimeMillis());
-               }
-            }
-
-            if (longestNameMatch == null || longestNameMatch.length() < entryName.length())
-            {
-               longestNameMatch = entryName; // keep entry name
-            }
-         }
-      }
-      if (longestNameMatch == null)
-         throw new IllegalArgumentException("Cannot find entry: " + is + ", " + relative);
-
-      // do recursion on relative
-      bais.reset();
-      zis = new ZipInputStream(bais);
-      while((entry = zis.getNextEntry()) != null)
-      {
-         String entryName = entry.getName();
-         if (entryName.equals(longestNameMatch))
-         {
-            relative = relative.substring(longestNameMatch.length() + 1);
-            return findEntry(zis, relative);
-         }
-      }
-      throw new IllegalArgumentException("No such entry: " + is + ", " + relative);
-   }
-
-   /**
-    * Returns archive file name - if this is a top-level ZipEntryContext.
-    * Otherwise it returns the last component of URL.
-    *
-    * @return name
-    */
-   public String getName()
-   {
-      VirtualFileHandler peer = getRootPeer();
-      if (peer != null)
-         return peer.getName();
-      else
-         return zipSource.getName();
-   }
-
-   /**
-    * Iterate through zip archive entries, compose a tree structure of archive's content
-    *
-    * @throws URISyntaxException for any URI error
-    * @throws java.io.IOException for any error
-    */
-   private synchronized void initEntries() throws IOException, URISyntaxException
-   {
-      // we're using a two phase approach - we first select the relevant ones
-      // then we order these by name and only then we process them
-      // this way we ensure that parent entries are processed before child entries
-
-      Map<String, ZipEntry> relevant = new HashMap<String, ZipEntry>();
-      zipSource.acquire();
-      try
-      {
-         Enumeration<? extends ZipEntry> zipEntries = zipSource.entries();
-         // zoom-in on entries under rootEntryPath - ignoring the rest
-         while(zipEntries.hasMoreElements())
-         {
-            ZipEntry ent = zipEntries.nextElement();
-            if(ent.getName().startsWith(rootEntryPath))
-            {
-               relevant.put(ent.getName(), ent);
-            }
-         }
-
-         Map<String, ZipEntry> orderedRelevant = new TreeMap<String, ZipEntry>(relevant);
-         for(Map.Entry<String, ZipEntry> entry : orderedRelevant.entrySet())
-         {
-            ZipEntry ent = entry.getValue();
-            String fullName = ent.getName().substring(rootEntryPath.length());
-
-            String [] split = splitParentChild(fullName);
-            String parentPath = split[0];
-            String name = split[1];
-
-            EntryInfo ei = null;
-            if ("".equals(name) == false)
-            {
-               ei = entries.get(parentPath);
-               if(ei == null)
-                  ei = makeDummyParent(parentPath);
-            }
-            AbstractVirtualFileHandler parent = ei != null ? ei.handler : null;
-
-            if(ent.isDirectory() == false && JarUtils.isArchive(ent.getName()))
-            {
-               boolean useCopyMode = forceCopy;
-               if (useCopyMode == false)
-               {
-                  String flag = getOptions().get(VFSUtils.USE_COPY_QUERY);
-                  useCopyMode = Boolean.valueOf(flag);
-               }
-
-               DelegatingHandler delegator;
-
-               if (useCopyMode)
-               {
-                  // extract it to temp dir
-                  File dest = new File(getTempDir() + "/" + getTempFileName(ent.getName()));
-                  dest.deleteOnExit();
-
-                  // ensure parent exists
-                  dest.getParentFile().mkdirs();
-
-                  InputStream is = zipSource.openStream(ent);
-                  OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
-                  VFSUtils.copyStreamAndClose(is, os);
-
-                  // mount another instance of ZipEntryContext
-                  delegator = mountZipFile(parent, name, dest);
-               }
-               else
-               {
-                  // mount another instance of ZipEntryContext
-                  delegator = mountZipStream(parent, name, zipSource.openStream(ent));
-               }
-
-               entries.put(delegator.getLocalPathName(), new EntryInfo(delegator, ent));
-               addChild(parent, delegator);
-            }
-            else
-            {
-               ZipEntryHandler wrapper = new ZipEntryHandler(this, parent, name, ent.isDirectory() == false);
-               entries.put(wrapper.getLocalPathName(), new EntryInfo(wrapper, ent));
-            }
-         }
-      }
-      finally
-      {
-         zipSource.release();
-      }
-   }
-
-   /**
-    * Perform initialization only if it hasn't been done yet
-    */
-   private synchronized void ensureEntries()
-   {
-      if (initStatus != InitializationStatus.NOT_INITIALIZED)
-         return;
-
-      try
-      {
-         initStatus = InitializationStatus.INITIALIZING;
-         initEntries();
-         initStatus = InitializationStatus.INITIALIZED;
-      }
-      catch (Exception ex)
-      {
-         throw new RuntimeException("Failed to read zip file: " + zipSource, ex);
-      }
-      finally
-      {
-         if (initStatus == InitializationStatus.INITIALIZING)
-            initStatus = InitializationStatus.NOT_INITIALIZED;
-      }
-   }
-
-   /**
-    * Mount ZipEntryContext created around extracted nested archive
-    *
-    * @param parent the parent
-    * @param name the name
-    * @param file the file
-    * @return mounted delegate
-    * @throws IOException for any error
-    * @throws URISyntaxException for any URI syntax error
-    */
-   protected DelegatingHandler mountZipFile(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
-   {
-      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
-      URL fileUrl = file.toURL();
-      URL delegatorUrl = fileUrl;
-
-      if (parent != null)
-         delegatorUrl = getChildURL(parent, name);
-
-      delegatorUrl = setOptionsToURL(delegatorUrl);
-      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl, true);
-      VirtualFileHandler handler = ctx.getRoot();
-      delegator.setDelegate(handler);
-
-      return delegator;
-   }
-
-   /**
-    * Mount ZipEntryContext created around ZipStreamWrapper
-    *
-    * @param parent the parent
-    * @param name the name
-    * @param zipStream the zip stream
-    * @return mounted delegate
-    * @throws IOException for any error
-    * @throws URISyntaxException for any URI syntax error
-    */
-   protected DelegatingHandler mountZipStream(VirtualFileHandler parent, String name, InputStream zipStream) throws IOException, URISyntaxException
-   {
-      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
-      ZipStreamWrapper wrapper = new ZipStreamWrapper(zipStream, name, parent.getLastModified());
-
-      URL delegatorUrl = null;
-
-      if (parent != null)
-         delegatorUrl = getChildURL(parent, name);
-
-      delegatorUrl = setOptionsToURL(delegatorUrl);
-      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, wrapper, false);
-      VirtualFileHandler handler = ctx.getRoot();
-      delegator.setDelegate(handler);
-
-      return delegator;
-   }
-
-   /**
-    * Zip archives sometimes don't contain directory entries - only leaf entries
-    *
-    * @param parentPath the parent path
-    * @return entry info
-    * @throws IOException for any error
-    */
-   private EntryInfo makeDummyParent(String parentPath) throws IOException
-   {
-      // get grand parent first
-      String [] split = splitParentChild(parentPath);
-      String grandPa = split[0];
-
-      EntryInfo eiParent = entries.get(grandPa);
-      if(eiParent == null)
-         eiParent = makeDummyParent(grandPa);
-
-      ZipEntryHandler handler = new ZipEntryHandler(this, eiParent.handler, split[1], false);
-      EntryInfo ei = new EntryInfo(handler, null);
-      entries.put(parentPath, ei);
-      return ei;
-   }
-
-   /**
-    * Initialize rootEntryPath and return archive file path
-    *
-    * @param localRootUrl local root url
-    * @return file path
-    */
-   private String initRootAndPath(URL localRootUrl)
-   {
-      String filePath = localRootUrl.toString();
-      String zipPath = filePath;
-
-      int pos = filePath.indexOf("!");
-      if(pos > 0)
-      {
-         zipPath = filePath.substring(0, pos);
-         rootEntryPath = filePath.substring(pos+2);
-         if(rootEntryPath.length() != 0)
-            rootEntryPath += "/";
-      }
-
-      // find where url protocol ends - i.e. jar:file:/ ...
-      pos= zipPath.indexOf(":/");
-      filePath = zipPath.substring(pos + 1);
-
-      // cut out url query part if present
-      int queryStart = filePath.indexOf("?");
-      if (queryStart != -1)
-         filePath = filePath.substring(0, queryStart);
-
-      return filePath;
-   }
-
-   /**
-    * If archive has been modified, clear <em>entries</em> and re-initialize.
-    * If not initialized yet, initialize it.
-    */
-   private synchronized void checkIfModified()
-   {
-      // TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
-      if (initStatus == InitializationStatus.NOT_INITIALIZED)
-      {
-         ensureEntries();
-      }
-      else if (initStatus == InitializationStatus.INITIALIZED && zipSource.hasBeenModified())
-      {
-         EntryInfo rootInfo = entries.get("");
-         entries = new ConcurrentHashMap<String, EntryInfo>();
-         entries.put("", rootInfo);
-
-         if (zipSource.exists())
-         {
-            try
-            {
-               initEntries();
-            }
-            catch(Exception ignored)
-            {
-               log.warn("IGNORING: Failed to reinitialize context: " + getRootURI(), ignored);
-            }
-         }
-      }
-   }
-
-   /**
-    * Returns this context's root
-    *
-    * @return root handler
-    */
-   public VirtualFileHandler getRoot()
-   {
-      return entries.get("").handler;
-   }
-
-   /**
-    * Find a child with a given name and a given parent
-    *
-    * @param parent parent handler
-    * @param name  name of the child
-    * @return child handler or null if not found
-    */
-   public VirtualFileHandler getChild(ZipEntryHandler parent, String name)
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Null parent");
-
-      checkIfModified();
-
-      String pathName = parent.getLocalPathName();
-      if("".equals(pathName))
-         pathName = name;
-      else
-         pathName = pathName + "/" + name;
-
-      EntryInfo ei = entries.get(pathName);
-      if(ei != null)
-         return ei.handler;
-
-      return null;
-   }
-
-   /**
-    * Returns a list of children for a given parent
-    *
-    * @param parent parent handler
-    * @param ignoreErrors true if errors should be silently ignored
-    * @return list of handlers representing children of the given parent
-    * @throws IOException for any error
-    */
-   public List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Null parent");
-
-      checkIfModified();
-      if(parent instanceof AbstractVirtualFileHandler)
-      {
-         AbstractVirtualFileHandler parentHandler  = (AbstractVirtualFileHandler) parent;
-         EntryInfo parentEntry = entries.get(parentHandler.getLocalPathName());
-         if (parentEntry != null)
-         {
-            if (parentEntry.handler instanceof DelegatingHandler)
-               return parentEntry.handler.getChildren(ignoreErrors);
-            
-            return parentEntry.getChildren();
-         }
-      }
-      return Collections.emptyList();
-   }
-
-   public boolean delete(ZipEntryHandler handler, int gracePeriod) throws IOException
-   {
-      if (getRoot().equals(handler))
-      {
-         return zipSource.delete(gracePeriod);
-      }
-      return false;
-   }
-
-   /**
-    * Returns lastModified timestamp for a given handler
-    *
-    * @param handler a handler
-    * @return lastModified timestamp
-    */
-   public long getLastModified(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      if (getRoot().equals(handler) == false)
-         checkIfModified();
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      if(ei == null)
-         return 0;
-
-      if(ei.entry == null) {
-         return zipSource.getLastModified();
-      }
-
-      return ei.entry.getTime();
-   }
-
-   /**
-    * Returns the size for a given handler
-    *
-    * @param handler a handler
-    * @return size in bytes
-    */
-   public long getSize(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      if(getRoot().equals(handler))
-         return zipSource.getSize();
-
-      checkIfModified();
-
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      if(ei == null || ei.entry == null)
-         return 0;
-
-      return ei.entry.getSize();
-   }
-
-   /**
-    * Returns true if entry exists for a given handler
-    *
-    * @param handler a handler
-    * @return true if entry exists
-    */
-   public boolean exists(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      if (getRoot().equals(handler))
-         return zipSource.exists();
-
-      checkIfModified();
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      return ei != null;
-   }
-
-   /**
-    * Returns true if handler represents a non-directory entry
-    *
-    * @param handler a handler
-    * @return true if not a directory
-    */
-   public boolean isLeaf(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      if (getRoot().equals(handler) == false)
-         checkIfModified();
-      
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      if (ei == null || ei.entry == null)
-         return false;
-
-      return ei.entry.isDirectory() == false;
-   }
-
-   /**
-    * Is archive.
-    *
-    * @param handler the handler
-    * @return true if archive
-    */
-   static boolean isArchive(VirtualFileHandler handler)
-   {
-      if (handler instanceof ZipEntryHandler && "".equals(handler.getLocalPathName()))
-      {
-         return true;
-      }
-
-      if (handler instanceof DelegatingHandler && ((DelegatingHandler) handler).getDelegate() instanceof ZipEntryHandler)
-      {
-         return true;
-      }
-
-      return false;
-   }
-
-   /**
-    * Get parent.
-    *
-    * @param handler the handler to check
-    * @return parent handler
-    * @throws IOException for any error
-    */
-   static VirtualFileHandler getParent(VirtualFileHandler handler) throws IOException
-   {
-      VirtualFileHandler parent = handler.getParent();
-      if (parent == null)
-      {
-         VirtualFileHandler peer = handler.getVFSContext().getRootPeer();
-         if (peer != null)
-            parent = peer.getParent();
-      }
-      return parent;
-   }
-
-   /**
-    * Is nested.
-    *
-    * @param handler the handler
-    * @return true if nested
-    * @throws IOException for any error
-    */
-   static boolean isNested(VirtualFileHandler handler) throws IOException
-   {
-      VirtualFileHandler parent = getParent(handler);
-      while (parent != null)
-      {
-         if(isArchive(parent))
-            return true;
-
-         parent = getParent(parent);
-      }
-      return false;
-   }
-
-   /**
-    * Contents of the file represented by a given handler
-    *
-    * @param handler a handler
-    * @return InputStream with entry's content
-    * @throws IOException for any error
-    */
-   public InputStream openStream(ZipEntryHandler handler) throws IOException
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      if (getRoot().equals(handler))
-         return zipSource.getRootAsStream();
-
-      checkIfModified();
-
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-
-      if (ei == null)
-      {
-         String uriStr;
-         try
-         {
-            uriStr = handler.toURI().toString();
-         }
-         catch(Exception ex)
-         {
-            throw new RuntimeException("ASSERTION ERROR - uri generation failed for ZipEntryHandler: " + handler, ex);
-         }
-         throw new FileNotFoundException(uriStr);
-      }
-
-      if(ei.entry == null)
-         return new ByteArrayInputStream(new byte[0]);
-
-      return zipSource.openStream(ei.entry);
-   }
-
-   /**
-    * Add a child to a given parent
-    *
-    * @param parent a parent
-    * @param child a child
-    */
-   public void addChild(AbstractVirtualFileHandler parent, AbstractVirtualFileHandler child)
-   {
-      if (parent == null)
-         throw new IllegalArgumentException("Null parent");
-
-      if (child == null)
-         throw new IllegalArgumentException("Null child");
-
-      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
-      if (parentEntry != null)
-         parentEntry.add(child);
-      else
-         throw new RuntimeException("Parent does not exist: " + parent);
-   }
-
-   /**
-    * Properly release held resources
-    */
-   protected void finalize()
-   {
-      try
-      {
-         super.finalize();
-         if (zipSource != null)
-            zipSource.close();
-      }
-      catch (Throwable ignored)
-      {
-         log.debug("IGNORING: Failed to close zip source: " + zipSource, ignored);
-      }
-   }
-
-   /**
-    * Replace a current child of the given parent with another one
-    *
-    * @param parent a parent
-    * @param original current child
-    * @param replacement new child
-    */
-   public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      ensureEntries();
-      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
-      if (parentEntry != null)
-      {
-         DelegatingHandler newOne;
-
-         if (replacement instanceof DelegatingHandler)
-         {
-            newOne = (DelegatingHandler) replacement;
-         }
-         else
-         {
-            newOne = new DelegatingHandler(this, parent, original.getName(), replacement);
-         }
-
-         synchronized(this)
-         {
-            parentEntry.replaceChild(original, newOne);
-
-            EntryInfo ei = entries.get(original.getLocalPathName());
-            ei.handler = newOne;
-            ei.entry = null;
-            ei.clearChildren();
-         }
-      }
-      else
-      {
-         throw new RuntimeException("Parent does not exist: " + parent);
-      }
-   }
-
-   /**
-    *  Internal data structure holding meta information of a virtual file in this context
-    */
-   static class EntryInfo
-   {
-      /** a handler */
-      private AbstractVirtualFileHandler handler;
-
-      /** a <tt>ZipEntry</tt> */
-      private ZipEntry entry;
-
-      /** a list of children */
-      private List<AbstractVirtualFileHandler> children;
-
-      /**
-       * EntryInfo constructor
-       *
-       * @param handler a handler
-       * @param entry an entry
-       */
-      EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
-      {
-         this.handler = handler;
-         this.entry = entry;
-      }
-
-      /**
-       * Get children.
-       *
-       * @return returns a list of children for this handler (by copy)
-       */
-      public synchronized List<VirtualFileHandler> getChildren()
-      {
-         if (children == null)
-            return Collections.emptyList();
-
-         return new LinkedList<VirtualFileHandler>(children);
-      }
-
-      /**
-       * Replace a child.
-       *
-       * @param original existing child
-       * @param replacement new child
-       */
-      public synchronized void replaceChild(AbstractVirtualFileHandler original, AbstractVirtualFileHandler replacement)
-      {
-         if (children != null)
-         {
-            int i = 0;
-            for (AbstractVirtualFileHandler child : children)
-            {
-               if (child.getName().equals(original.getName()))
-               {
-                  children.set(i, replacement);
-                  break;
-               }
-               i++;
-            }
-         }
-      }
-
-      /**
-       * Clear the list of children
-       */
-      public synchronized void clearChildren()
-      {
-         if (children != null)
-            children.clear();
-      }
-
-      /**
-       * Add a child. If a child with the same name exists already, first remove it.
-       *
-       * @param child a child
-       */
-      public synchronized void add(AbstractVirtualFileHandler child)
-      {
-         if (children == null)
-         {
-            children = new LinkedList<AbstractVirtualFileHandler>();
-         }
-         else
-         {
-            // if a child exists with this name already, remove it
-            Iterator<AbstractVirtualFileHandler> it = children.iterator();
-            while (it.hasNext())
-            {
-               AbstractVirtualFileHandler handler = it.next();
-               if (handler.getName().equals(child.getName()))
-               {
-                  it.remove();
-                  break;
-               }
-            }
-         }
-
-         children.add(child);
-      }
-   }
-
-
-
-   //
-   //   Helper methods
-   //
-
-
-   /**
-    * Make sure url protocol is <em>vfszip</em>
-    *
-    * @param rootURL the root url
-    * @return fixed url
-    * @throws MalformedURLException for any error
-    */
-   private static URL fixUrl(URL rootURL) throws MalformedURLException
-   {
-      if ("vfszip".equals(rootURL.getProtocol()) == false)
-      {
-         String url = rootURL.toString();
-         int pos = url.indexOf(":/");
-         if (pos != -1)
-            url = url.substring(pos);
-
-         return new URL("vfszip" + url);
-      }
-      return rootURL;
-   }
-
-   /**
-    * Break to path + name
-    *
-    * @param pathName the path name
-    * @return path tokens
-    */
-   public static String [] splitParentChild(String pathName)
-   {
-      if (pathName.startsWith("/"))
-         pathName = pathName.substring(1);
-      
-      if(pathName.length() == 0)
-         return new String [] {null, pathName};
-
-      int toPos = pathName.length();
-      if(pathName.charAt(pathName.length()-1) == '/')
-         toPos --;
-
-      int delimPos = pathName.lastIndexOf('/', toPos-1);
-
-      String [] ret;
-      if(delimPos == -1)
-      {
-         ret = new String []
-         {
-            "",
-            pathName.substring(delimPos+1, toPos)
-         };
-      }
-      else
-      {
-         ret = new String []
-         {
-            pathName.substring(0, delimPos),
-            pathName.substring(delimPos+1, toPos)
-         };
-      }
-      return ret;
-   }
-
-   /**
-    * Temporary files naming scheme
-    *
-    * @param name the name
-    * @return random name
-    */
-   private static String getTempFileName(String name)
-   {
-      int delim = name.lastIndexOf("/");
-      if (delim != -1)
-         name = name.substring(delim+1);
-      return UUID.randomUUID().toString().substring(0, 8) + "_" + name;
-   }
-
-   /**
-    * Use VFS's temp directory and make 'vfs-nested.tmp' sub-directory inside it for our purposes
-    *
-    * @return temp dir
-    */
-   private static String getTempDir()
-   {
-      File dir = new File(AbstractCopyMechanism.getTempDirectory(), "vfs-nested.tmp");
-      return dir.toString();
-   }
-
-   /**
-    * Delete the contents of a temporary directory. Delete first-level files only, don't drill down.
-    */
-   private static void deleteTmpDirContents()
-   {
-      try
-      {
-         File tmpDir = new File(getTempDir());
-         File [] files = tmpDir.listFiles();
-         if (files != null && files.length > 0)
-         {            
-            for (File file : files)
-            {
-               if (file.isDirectory() == false && file.isHidden() == false)
-                  file.delete();
-            }
-         }
-      }
-      catch(Exception ignored)
-      {
-      }
-   }
-
-   /**
-    * <tt>PriviligedAction</tt> class for checking a system property
-    */
-   private static class CheckForceCopy implements PrivilegedAction<Boolean>
-   {
-      public Boolean run()
-      {
-         String forceString = System.getProperty(VFSUtils.FORCE_COPY_KEY, "false");
-         return Boolean.valueOf(forceString);
-      }
-   }
-
-   static enum InitializationStatus {
-      NOT_INITIALIZED,
-      INITIALIZING,
-      INITIALIZED
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,1333 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractVFSContext;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.plugins.copy.AbstractCopyMechanism;
+import org.jboss.virtual.spi.ExceptionHandler;
+import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * <tt>ZipEntryContext</tt> implements a {@link org.jboss.virtual.spi.VFSContext}
+ * that exposes a zip archive as a virtual file system.
+ *
+ * Zip archive can be in a form of a file or a stream.
+ *
+ * Nested archives are processed through this same class.
+ * By default nested archives are cached in memory and mounted as new
+ * instances of <tt>ZipEntryContext</tt> with <tt>ZipStreamWrapper</tt> as a source.
+ * If system property <em>jboss.vfs.forceCopy=true</em> is specified,
+ * or URL query parameter <em>forceCopy=true</em> is present,
+ * nested archives are extracted into a temp directory before being
+ * mounted as new instances of <tt>ZipEntryContext</tt>.
+ *
+ * In-memory nested archives may consume a lot of memory. To reduce memory footprint
+ * at the expense of performance, system property <em>jboss.vfs.optimizeForMemory=true<em>
+ * can be set.
+ *
+ * This context implementation has two modes of releasing file locks.
+ * <em>Asynchronous</em> mode is the default one since it is better performant.
+ * To switch this to <em>synchronous</em> mode a system property
+ * <em>jboss.vfs.forceNoReaper=true</em> can be specified or URL query parameter
+ * <em>noReaper=true</em> can be included in context URL.
+ *
+ * This context implementation is a replacement for
+ * {@link org.jboss.virtual.plugins.context.jar.JarContext}.
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @author <a href="ales.justin at jboss.org">Ales Justin</a>
+ * @version $Revision: 1.0 $
+ */
+public class ZipEntryContext extends AbstractVFSContext
+{
+   /** Logger */
+   private static final Logger log = Logger.getLogger(ZipEntryContext.class);
+
+   /** Global setting for nested archive processing mode: copy or no-copy (default) */
+   private static boolean forceCopy;
+
+   static
+   {
+      deleteTmpDirContents();
+
+      forceCopy = AccessController.doPrivileged(new CheckForceCopy());
+
+      if (forceCopy)
+         log.info("VFS force nested jars copy-mode is enabled.");
+   }
+
+   /** Abstracted access to zip archive - either ZipFileWrapper or ZipStreamWrapper */
+   private ZipWrapper zipSource;
+
+   /** Entry path representing a context root - archive root is not necessarily a context root */
+   private String rootEntryPath = "";
+
+   /** path to zip file - used for lazy ZipWrapper initialization */
+   private String filePath = null;
+
+   /** AutoClean signals if zip archive should be deleted after closing the context - true for nested archives */
+   private boolean autoClean = false;
+
+   /** Registry of everything that zipSource contains */
+   private Map<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
+
+   /** Have zip entries been navigated yet */
+   private InitializationStatus initStatus = InitializationStatus.NOT_INITIALIZED;
+
+   /** RealURL of this context */
+   private URL realURL;
+
+   /**
+    * Create a new ZipEntryContext
+    *
+    * @param rootURL - file or jar:file url
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   public ZipEntryContext(URL rootURL) throws URISyntaxException, IOException
+   {
+      this(rootURL, false);
+   }
+
+   /**
+    * Create a new ZipEntryContext
+    *
+    * @param rootURL - file or jar:file url
+    * @param autoClean - true if file represented by rootURL should be deleted after this context is closed
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   public ZipEntryContext(URL rootURL, boolean autoClean) throws URISyntaxException, IOException
+   {
+      super(VFSUtils.toURI(fixUrl(rootURL)));
+      this.autoClean = autoClean;
+      init(rootURL, null, null);
+   }
+
+   /**
+    * Create a new ZipEntryContext to be mounted into another context
+    *
+    * @param rootURL - url representing this context within another context
+    * @param peer - file handler in another context through which this context is being mounted
+    * @param localRootUrl - file or jar:file url
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl) throws URISyntaxException, IOException
+   {
+      this(rootURL, peer, localRootUrl, false);
+   }
+
+   /**
+    * Create a new ZipEntryContext to be mounted into another context
+    *
+    * @param rootURL - url representing this context within another context
+    * @param peer - file handler in another context through which this context is being mounted
+    * @param localRootUrl - file or jar:file url
+    * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl, boolean autoClean) throws URISyntaxException, IOException
+   {
+      super(VFSUtils.toURI(fixUrl(rootURL)));
+      this.autoClean = autoClean;
+      init(localRootUrl, peer, null);
+   }
+
+   /**
+    * Create a new ZipEntryContext to be mounted into another context
+    *
+    * @param rootURL - url representing this context within another context
+    * @param peer - file handler in another context through which this context is being mounted
+    * @param zipWrapper - abstracted zip archive source
+    * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, ZipWrapper zipWrapper, boolean autoClean) throws URISyntaxException, IOException
+   {
+      super(VFSUtils.toURI(fixUrl(rootURL)));
+      this.autoClean = autoClean;
+      init(null, peer, zipWrapper);
+   }
+
+   /**
+    * Extra initialization in addition to what's inside constructors
+    *
+    * @param localRootURL the local url
+    * @param peer the peer
+    * @param zipWrapper zip wrapper
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   private void init(URL localRootURL, VirtualFileHandler peer, ZipWrapper zipWrapper) throws IOException, URISyntaxException
+   {
+      if (zipWrapper == null)
+      {
+         if (localRootURL == null)
+            throw new IllegalArgumentException("No ZipWrapper specified and localRootURL is null");
+
+         // initialize rootEntryPath and get archive file path
+         filePath = initRootAndPath(localRootURL);
+      }
+      else
+      {
+         zipSource = zipWrapper;
+      }
+      
+      setRootPeer(peer);
+      String name = getRootURI().getPath();
+      int toPos = name.length();
+
+      // cut off any ending slash
+      if(name.length() != 0 && name.charAt(name.length()-1) == '/')
+         toPos --;
+
+      // name is last path component
+      int namePos = name.lastIndexOf("/", toPos-1);
+      name = name.substring(namePos+1, toPos);
+      
+      // cut off any ending exclamation
+      if(name.length() != 0 && name.charAt(name.length()-1) == '!')
+         name = name.substring(0, name.length()-1);
+
+      // init initial root EntryInfo that will be overwritten
+      // if zip entry exists for rootEntryPath
+      entries.put("", new EntryInfo(new ZipEntryHandler(this, null, name, true), null));
+
+      // It's lazy init now
+      //initEntries();
+   }
+
+   /**
+    * Get zip source.
+    * Lazy init.
+    *
+    * @return the zip source
+    */
+   protected synchronized ZipWrapper getZipSource()
+   {
+      if (zipSource == null)
+      {
+         try
+         {
+            zipSource = createZipSource(filePath);
+         }
+         catch (IOException e)
+         {
+            throw new RuntimeException("Failed to initialize ZipWrapper: " + filePath, e);
+         }
+      }
+      return zipSource;
+   }
+
+   /**
+    * Returns aggregated options.
+    *
+    * If peer exists, it uses peer context's options as a basis,
+    * and overrides them with this context's options.
+    *
+    * @return map containing aggregated options
+    */
+   public Map<String, String> getAggregatedOptions()
+   {
+      Map<String, String> options = new HashMap<String, String>();
+      VFSContext peerContext = getPeerContext();
+      if (peerContext != null)
+         options.putAll(peerContext.getOptions());
+      options.putAll(super.getOptions()); // put them after peer, possible override
+      return options;
+   }
+
+   public ExceptionHandler getExceptionHandler()
+   {
+      ExceptionHandler eh = super.getExceptionHandler();
+      if (eh != null)
+         return eh;
+
+      VFSContext peerContext = getPeerContext();
+      return peerContext != null ? peerContext.getExceptionHandler() : null;
+   }
+
+   /**
+    * Create zip source.
+    *
+    * @param rootPath the root path
+    * @return zip entry wrapper
+    * @throws IOException for any error
+    */
+   protected ZipWrapper createZipSource(String rootPath) throws IOException
+   {
+      File file = null;
+      String relative = null;
+      File fp = new File(rootPath);
+      if (fp.exists())
+      {
+         file = fp;
+      }
+      else
+      {
+         File curr = fp;
+         relative = fp.getName();
+         while ((curr = curr.getParentFile()) != null)
+         {
+            if (curr.exists())
+            {
+               file = curr;
+               break;
+            }
+            else
+            {
+               relative = curr.getName() + "/" + relative;
+            }
+         }
+      }
+
+      if (file == null)
+         throw new IOException("VFS file does not exist: " + rootPath);
+
+      RealURLInfo urlInfo = new RealURLInfo(file);
+
+      if (relative != null)
+      {
+         ZipWrapper wrapper = findEntry(new FileInputStream(file), relative, urlInfo);
+         realURL = urlInfo.toURL();
+         return wrapper;
+      }
+      else
+      {
+         boolean noReaper = Boolean.valueOf(getAggregatedOptions().get(VFSUtils.NO_REAPER_QUERY));
+         realURL = urlInfo.toURL();
+         return new ZipFileWrapper(file, autoClean, noReaper);
+      }
+   }
+
+   /**
+    * Find exact entry.
+    * Use recursion on relative path.
+    *
+    * @param is the input stream
+    * @param relative relative path
+    * @param urlInfo url info
+    * @return zip wrapper instance
+    * @throws IOException for any error
+    */
+   protected ZipWrapper findEntry(InputStream is, String relative, RealURLInfo urlInfo) throws IOException
+   {
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      VFSUtils.copyStreamAndClose(is, baos);
+      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+
+      // first we need to find best/longest name
+      ZipInputStream zis = new ZipInputStream(bais);
+      ZipEntry entry;
+      String longestNameMatch = null;
+      while((entry = zis.getNextEntry()) != null)
+      {
+         String entryName = entry.getName();
+         String match = entryName;
+         if (entry.isDirectory())
+            match = match.substring(0, match.length() - 1);
+
+         if (relative.startsWith(match))
+         {
+            if (match.equals(relative))
+            {
+               if (entry.isDirectory())
+               {
+                  this.rootEntryPath = relative;
+                  return new ZipDirWrapper(zis, entryName, System.currentTimeMillis(), bais);
+               }
+               else if (JarUtils.isArchive(match) == false)
+               {
+                  return new ZipEntryWrapper(zis, entryName, System.currentTimeMillis());
+               }
+               else
+               {
+                  return new ZipStreamWrapper(zis, entryName, System.currentTimeMillis());
+               }
+            }
+
+            if (longestNameMatch == null || longestNameMatch.length() < entryName.length())
+            {
+               longestNameMatch = entryName; // keep entry name
+            }
+         }
+      }
+      if (longestNameMatch == null)
+         throw new IllegalArgumentException("Cannot find entry: " + is + ", " + relative);
+
+      // do recursion on relative
+      bais.reset();
+      zis = new ZipInputStream(bais);
+      while((entry = zis.getNextEntry()) != null)
+      {
+         String entryName = entry.getName();
+         if (entryName.equals(longestNameMatch))
+         {
+            if (urlInfo != null)
+               urlInfo.relativePath = longestNameMatch;
+
+            relative = relative.substring(longestNameMatch.length() + 1);
+            return findEntry(zis, relative, null);
+         }
+      }
+      throw new IllegalArgumentException("No such entry: " + is + ", " + relative);
+   }
+
+   /**
+    * Returns archive file name - if this is a top-level ZipEntryContext.
+    * Otherwise it returns the last component of URL.
+    *
+    * @return name
+    */
+   public String getName()
+   {
+      VirtualFileHandler peer = getRootPeer();
+      if (peer != null)
+         return peer.getName();
+      else
+         return getZipSource().getName();
+   }
+
+   /**
+    * Iterate through zip archive entries, compose a tree structure of archive's content
+    *
+    * @throws URISyntaxException for any URI error
+    * @throws java.io.IOException for any error
+    */
+   private synchronized void initEntries() throws IOException, URISyntaxException
+   {
+      // we're using a two phase approach - we first select the relevant ones
+      // then we order these by name and only then we process them
+      // this way we ensure that parent entries are processed before child entries
+
+      Map<String, ZipEntry> relevant = new HashMap<String, ZipEntry>();
+      ZipWrapper zipSource = getZipSource();
+      zipSource.acquire();
+      try
+      {
+         Enumeration<? extends ZipEntry> zipEntries = zipSource.entries();
+         // zoom-in on entries under rootEntryPath - ignoring the rest
+         while(zipEntries.hasMoreElements())
+         {
+            ZipEntry ent = zipEntries.nextElement();
+            if(ent.getName().startsWith(rootEntryPath))
+            {
+               relevant.put(ent.getName(), ent);
+            }
+         }
+
+         Map<String, ZipEntry> orderedRelevant = new TreeMap<String, ZipEntry>(relevant);
+         for(Map.Entry<String, ZipEntry> entry : orderedRelevant.entrySet())
+         {
+            ZipEntry ent = entry.getValue();
+            String fullName = ent.getName().substring(rootEntryPath.length());
+
+            String [] split = splitParentChild(fullName);
+            String parentPath = split[0];
+            String name = split[1];
+
+            EntryInfo ei = null;
+            if ("".equals(name) == false)
+            {
+               ei = entries.get(parentPath);
+               if(ei == null)
+                  ei = makeDummyParent(parentPath);
+            }
+            AbstractVirtualFileHandler parent = ei != null ? ei.handler : null;
+
+            if(ent.isDirectory() == false && JarUtils.isArchive(ent.getName()))
+            {
+               boolean useCopyMode = forceCopy;
+               if (useCopyMode == false)
+               {
+                  String flag = getAggregatedOptions().get(VFSUtils.USE_COPY_QUERY);
+                  useCopyMode = Boolean.valueOf(flag);
+               }
+
+               DelegatingHandler delegator;
+
+               if (useCopyMode)
+               {
+                  // extract it to temp dir
+                  File dest = new File(getTempDir() + "/" + getTempFileName(ent.getName()));
+                  dest.deleteOnExit();
+
+                  // ensure parent exists
+                  dest.getParentFile().mkdirs();
+
+                  InputStream is = zipSource.openStream(ent);
+                  OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
+                  VFSUtils.copyStreamAndClose(is, os);
+
+                  // mount another instance of ZipEntryContext
+                  delegator = mountZipFile(parent, name, dest);
+               }
+               else
+               {
+                  // mount another instance of ZipEntryContext
+                  delegator = mountZipStream(parent, name, zipSource.openStream(ent));
+               }
+
+               entries.put(delegator.getLocalPathName(), new EntryInfo(delegator, ent));
+               addChild(parent, delegator);
+            }
+            else
+            {
+               ZipEntryHandler wrapper = new ZipEntryHandler(this, parent, name, ent.isDirectory() == false);
+               entries.put(wrapper.getLocalPathName(), new EntryInfo(wrapper, ent));
+            }
+         }
+      }
+      finally
+      {
+         zipSource.release();
+      }
+   }
+
+   /**
+    * Perform initialization only if it hasn't been done yet
+    */
+   private synchronized void ensureEntries()
+   {
+      if (initStatus != InitializationStatus.NOT_INITIALIZED)
+         return;
+
+      try
+      {
+         initStatus = InitializationStatus.INITIALIZING;
+         initEntries();
+         initStatus = InitializationStatus.INITIALIZED;
+      }
+      catch (Exception ex)
+      {
+         ExceptionHandler eh = getExceptionHandler();
+         if (eh != null)
+            eh.handleZipEntriesInitException(ex, getZipSource().getName());
+         else
+            throw new RuntimeException("Failed to read zip file: " + getZipSource(), ex);
+      }
+      finally
+      {
+         if (initStatus == InitializationStatus.INITIALIZING)
+            initStatus = InitializationStatus.NOT_INITIALIZED;
+      }
+   }
+
+   /**
+    * Mount ZipEntryContext created around extracted nested archive
+    *
+    * @param parent the parent
+    * @param name the name
+    * @param file the file
+    * @return mounted delegate
+    * @throws IOException for any error
+    * @throws URISyntaxException for any URI syntax error
+    */
+   protected DelegatingHandler mountZipFile(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
+   {
+      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+      URL fileUrl = file.toURL();
+      URL delegatorUrl = fileUrl;
+
+      if (parent != null)
+         delegatorUrl = getChildURL(parent, name);
+
+      delegatorUrl = setOptionsToURL(delegatorUrl);
+      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl, true);
+
+      VirtualFileHandler handler = ctx.getRoot();
+      delegator.setDelegate(handler);
+
+      return delegator;
+   }
+
+   /**
+    * Mount ZipEntryContext created around ZipStreamWrapper
+    *
+    * @param parent the parent
+    * @param name the name
+    * @param zipStream the zip stream
+    * @return mounted delegate
+    * @throws IOException for any error
+    * @throws URISyntaxException for any URI syntax error
+    */
+   protected DelegatingHandler mountZipStream(VirtualFileHandler parent, String name, InputStream zipStream) throws IOException, URISyntaxException
+   {
+      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+      ZipStreamWrapper wrapper = new ZipStreamWrapper(zipStream, name, parent.getLastModified());
+
+      URL delegatorUrl = null;
+
+      if (parent != null)
+         delegatorUrl = getChildURL(parent, name);
+
+      delegatorUrl = setOptionsToURL(delegatorUrl);
+      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, wrapper, false);
+
+      VirtualFileHandler handler = ctx.getRoot();
+      delegator.setDelegate(handler);
+
+      return delegator;
+   }
+
+   /**
+    * Zip archives sometimes don't contain directory entries - only leaf entries
+    *
+    * @param parentPath the parent path
+    * @return entry info
+    * @throws IOException for any error
+    */
+   private EntryInfo makeDummyParent(String parentPath) throws IOException
+   {
+      // get grand parent first
+      String [] split = splitParentChild(parentPath);
+      String grandPa = split[0];
+
+      EntryInfo eiParent = entries.get(grandPa);
+      if(eiParent == null)
+         eiParent = makeDummyParent(grandPa);
+
+      ZipEntryHandler handler = new ZipEntryHandler(this, eiParent.handler, split[1], false);
+      EntryInfo ei = new EntryInfo(handler, null);
+      entries.put(parentPath, ei);
+      return ei;
+   }
+
+   /**
+    * Initialize rootEntryPath and return archive file path
+    *
+    * @param localRootUrl local root url
+    * @return file path
+    */
+   private String initRootAndPath(URL localRootUrl)
+   {
+      String filePath = localRootUrl.toString();
+      String zipPath = filePath;
+
+      int pos = filePath.indexOf("!");
+      if(pos > 0)
+      {
+         zipPath = filePath.substring(0, pos);
+         rootEntryPath = filePath.substring(pos+2);
+         if(rootEntryPath.length() != 0)
+            rootEntryPath += "/";
+      }
+
+      // find where url protocol ends - i.e. jar:file:/ ...
+      pos= zipPath.indexOf(":/");
+      filePath = zipPath.substring(pos + 1);
+
+      // cut out url query part if present
+      int queryStart = filePath.indexOf("?");
+      if (queryStart != -1)
+         filePath = filePath.substring(0, queryStart);
+
+      return filePath;
+   }
+
+   /**
+    * If archive has been modified, clear <em>entries</em> and re-initialize.
+    * If not initialized yet, initialize it.
+    */
+   private synchronized void checkIfModified()
+   {
+      // TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
+      if (initStatus == InitializationStatus.NOT_INITIALIZED)
+      {
+         ensureEntries();
+      }
+      else if (initStatus == InitializationStatus.INITIALIZED && getZipSource().hasBeenModified())
+      {
+         EntryInfo rootInfo = entries.get("");
+         entries = new ConcurrentHashMap<String, EntryInfo>();
+         entries.put("", rootInfo);
+
+         if (getZipSource().exists())
+         {
+            try
+            {
+               initEntries();
+            }
+            catch(Exception ignored)
+            {
+               log.warn("IGNORING: Failed to reinitialize context: " + getRootURI(), ignored);
+            }
+         }
+      }
+   }
+
+   /**
+    * Returns this context's root
+    *
+    * @return root handler
+    */
+   public VirtualFileHandler getRoot()
+   {
+      return entries.get("").handler;
+   }
+
+   /**
+    * Find a child with a given name and a given parent
+    *
+    * @param parent parent handler
+    * @param name  name of the child
+    * @return child handler or null if not found
+    */
+   public VirtualFileHandler getChild(ZipEntryHandler parent, String name)
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Null parent");
+
+      checkIfModified();
+
+      String pathName = parent.getLocalPathName();
+      if("".equals(pathName))
+         pathName = name;
+      else
+         pathName = pathName + "/" + name;
+
+      EntryInfo ei = entries.get(pathName);
+      if(ei != null)
+         return ei.handler;
+
+      return null;
+   }
+
+   /**
+    * Returns a list of children for a given parent
+    *
+    * @param parent parent handler
+    * @param ignoreErrors true if errors should be silently ignored
+    * @return list of handlers representing children of the given parent
+    * @throws IOException for any error
+    */
+   public List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Null parent");
+
+      checkIfModified();
+      if(parent instanceof AbstractVirtualFileHandler)
+      {
+         AbstractVirtualFileHandler parentHandler  = (AbstractVirtualFileHandler) parent;
+         EntryInfo parentEntry = entries.get(parentHandler.getLocalPathName());
+         if (parentEntry != null)
+         {
+            if (parentEntry.handler instanceof DelegatingHandler)
+               return parentEntry.handler.getChildren(ignoreErrors);
+            
+            return parentEntry.getChildren();
+         }
+      }
+      return Collections.emptyList();
+   }
+
+   /**
+    * Do delete.
+    *
+    * @param handler the zip entry handler
+    * @param gracePeriod the grace period
+    * @return true if delete succeeded
+    * @throws IOException for any error
+    */
+   public boolean delete(ZipEntryHandler handler, int gracePeriod) throws IOException
+   {
+      return getRoot().equals(handler) && getZipSource().delete(gracePeriod);
+   }
+
+   /**
+    * Returns lastModified timestamp for a given handler
+    *
+    * @param handler a handler
+    * @return lastModified timestamp
+    */
+   public long getLastModified(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      if (getRoot().equals(handler) == false)
+         checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null)
+         return 0;
+
+      if(ei.entry == null) {
+         return getZipSource().getLastModified();
+      }
+
+      return ei.entry.getTime();
+   }
+
+   /**
+    * Returns the size for a given handler
+    *
+    * @param handler a handler
+    * @return size in bytes
+    */
+   public long getSize(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      if(getRoot().equals(handler))
+         return getZipSource().getSize();
+
+      checkIfModified();
+
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null || ei.entry == null)
+         return 0;
+
+      return ei.entry.getSize();
+   }
+
+   /**
+    * Returns true if entry exists for a given handler
+    *
+    * @param handler a handler
+    * @return true if entry exists
+    */
+   public boolean exists(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      if (getRoot().equals(handler))
+         return getZipSource().exists();
+
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      return ei != null;
+   }
+
+   /**
+    * Returns true if handler represents a non-directory entry
+    *
+    * @param handler a handler
+    * @return true if not a directory
+    */
+   public boolean isLeaf(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      if (getRoot().equals(handler) == false)
+         checkIfModified();
+      
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if (ei == null || ei.entry == null)
+         return false;
+
+      return ei.entry.isDirectory() == false;
+   }
+
+   /**
+    * Is archive.
+    *
+    * @param handler the handler
+    * @return true if archive
+    */
+   static boolean isArchive(VirtualFileHandler handler)
+   {
+      if (handler instanceof ZipEntryHandler && "".equals(handler.getLocalPathName()))
+      {
+         return true;
+      }
+
+      if (handler instanceof DelegatingHandler && ((DelegatingHandler) handler).getDelegate() instanceof ZipEntryHandler)
+      {
+         return true;
+      }
+
+      return false;
+   }
+
+   /**
+    * Get parent.
+    *
+    * @param handler the handler to check
+    * @return parent handler
+    * @throws IOException for any error
+    */
+   static VirtualFileHandler getParent(VirtualFileHandler handler) throws IOException
+   {
+      VirtualFileHandler parent = handler.getParent();
+      if (parent == null)
+      {
+         VirtualFileHandler peer = handler.getVFSContext().getRootPeer();
+         if (peer != null)
+            parent = peer.getParent();
+      }
+      return parent;
+   }
+
+   /**
+    * Is nested.
+    *
+    * @param handler the handler
+    * @return true if nested
+    * @throws IOException for any error
+    */
+   static boolean isNested(VirtualFileHandler handler) throws IOException
+   {
+      VirtualFileHandler parent = getParent(handler);
+      while (parent != null)
+      {
+         if(isArchive(parent))
+            return true;
+
+         parent = getParent(parent);
+      }
+      return false;
+   }
+
+   /**
+    * Contents of the file represented by a given handler
+    *
+    * @param handler a handler
+    * @return InputStream with entry's content
+    * @throws IOException for any error
+    */
+   public InputStream openStream(ZipEntryHandler handler) throws IOException
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      if (getRoot().equals(handler))
+         return getZipSource().getRootAsStream();
+
+      checkIfModified();
+
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+
+      if (ei == null)
+      {
+         String uriStr;
+         try
+         {
+            uriStr = handler.toURI().toString();
+         }
+         catch(Exception ex)
+         {
+            throw new RuntimeException("ASSERTION ERROR - uri generation failed for ZipEntryHandler: " + handler, ex);
+         }
+         throw new FileNotFoundException(uriStr);
+      }
+
+      if(ei.entry == null)
+         return new ByteArrayInputStream(new byte[0]);
+
+      return getZipSource().openStream(ei.entry);
+   }
+
+   /**
+    * Add a child to a given parent
+    *
+    * @param parent a parent
+    * @param child a child
+    */
+   public void addChild(AbstractVirtualFileHandler parent, AbstractVirtualFileHandler child)
+   {
+      if (parent == null)
+         throw new IllegalArgumentException("Null parent");
+
+      if (child == null)
+         throw new IllegalArgumentException("Null child");
+
+      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
+      if (parentEntry != null)
+         parentEntry.add(child);
+      else
+         throw new RuntimeException("Parent does not exist: " + parent);
+   }
+
+   /**
+    * Properly release held resources
+    */
+   protected void finalize()
+   {
+      try
+      {
+         super.finalize();
+         if (zipSource != null)
+            zipSource.close();
+      }
+      catch (Throwable ignored)
+      {
+         log.debug("IGNORING: Failed to close zip source: " + zipSource, ignored);
+      }
+   }
+
+   /**
+    * Replace a current child of the given parent with another one
+    *
+    * @param parent a parent
+    * @param original current child
+    * @param replacement new child
+    */
+   public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      ensureEntries();
+      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
+      if (parentEntry != null)
+      {
+         DelegatingHandler newOne;
+
+         if (replacement instanceof DelegatingHandler)
+         {
+            newOne = (DelegatingHandler) replacement;
+         }
+         else
+         {
+            newOne = new DelegatingHandler(this, parent, original.getName(), replacement);
+         }
+
+         synchronized(this)
+         {
+            parentEntry.replaceChild(original, newOne);
+
+            EntryInfo ei = entries.get(original.getLocalPathName());
+            ei.handler = newOne;
+            ei.entry = null;
+            ei.clearChildren();
+         }
+      }
+      else
+      {
+         throw new RuntimeException("Parent does not exist: " + parent);
+      }
+   }
+
+   /**
+    * Get RealURL corresponding to root handler
+    *
+    * @return the real url
+    */
+   public URL getRealURL()
+   {
+      // make sure realURL has been initialized
+      // realURL is initialized when ZipSource is initialized
+      getZipSource();
+      return realURL;
+   }
+
+   /**
+    *  Internal data structure holding meta information of a virtual file in this context
+    */
+   static class EntryInfo
+   {
+      /** a handler */
+      private AbstractVirtualFileHandler handler;
+
+      /** a <tt>ZipEntry</tt> */
+      private ZipEntry entry;
+
+      /** a list of children */
+      private List<AbstractVirtualFileHandler> children;
+
+      /**
+       * EntryInfo constructor
+       *
+       * @param handler a handler
+       * @param entry an entry
+       */
+      EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
+      {
+         this.handler = handler;
+         this.entry = entry;
+      }
+
+      /**
+       * Get children.
+       *
+       * @return returns a list of children for this handler (by copy)
+       */
+      public synchronized List<VirtualFileHandler> getChildren()
+      {
+         if (children == null)
+            return Collections.emptyList();
+
+         return new LinkedList<VirtualFileHandler>(children);
+      }
+
+      /**
+       * Replace a child.
+       *
+       * @param original existing child
+       * @param replacement new child
+       */
+      public synchronized void replaceChild(AbstractVirtualFileHandler original, AbstractVirtualFileHandler replacement)
+      {
+         if (children != null)
+         {
+            int i = 0;
+            for (AbstractVirtualFileHandler child : children)
+            {
+               if (child.getName().equals(original.getName()))
+               {
+                  children.set(i, replacement);
+                  break;
+               }
+               i++;
+            }
+         }
+      }
+
+      /**
+       * Clear the list of children
+       */
+      public synchronized void clearChildren()
+      {
+         if (children != null)
+            children.clear();
+      }
+
+      /**
+       * Add a child. If a child with the same name exists already, first remove it.
+       *
+       * @param child a child
+       */
+      public synchronized void add(AbstractVirtualFileHandler child)
+      {
+         if (children == null)
+         {
+            children = new LinkedList<AbstractVirtualFileHandler>();
+         }
+         else
+         {
+            // if a child exists with this name already, remove it
+            Iterator<AbstractVirtualFileHandler> it = children.iterator();
+            while (it.hasNext())
+            {
+               AbstractVirtualFileHandler handler = it.next();
+               if (handler.getName().equals(child.getName()))
+               {
+                  it.remove();
+                  break;
+               }
+            }
+         }
+
+         children.add(child);
+      }
+   }
+
+   /**
+    * Make sure url protocol is <em>vfszip</em>.
+    * Also remove any '!' from URL
+    *
+    * @param rootURL the root url
+    * @return fixed url
+    * @throws MalformedURLException for any error
+    */
+   private static URL fixUrl(URL rootURL) throws MalformedURLException
+   {
+      String urlStr = rootURL.toExternalForm();
+      int pos = urlStr.indexOf("!");
+      if (pos != -1)
+      {
+         String tmp = urlStr.substring(0, pos);
+         if (pos < urlStr.length()-1)
+            tmp += urlStr.substring(pos+1);
+         urlStr = tmp;
+      }
+      if ("vfszip".equals(rootURL.getProtocol()) == false)
+      {
+         pos = urlStr.indexOf(":/");
+         if (pos != -1)
+            urlStr = urlStr.substring(pos);
+
+         return new URL("vfszip" + urlStr);
+      }
+      return rootURL;
+   }
+
+   /**
+    * Break to path + name
+    *
+    * @param pathName the path name
+    * @return path tokens
+    */
+   public static String [] splitParentChild(String pathName)
+   {
+      if (pathName.startsWith("/"))
+         pathName = pathName.substring(1);
+      
+      if(pathName.length() == 0)
+         return new String [] {null, pathName};
+
+      int toPos = pathName.length();
+      if(pathName.charAt(pathName.length()-1) == '/')
+         toPos --;
+
+      int delimPos = pathName.lastIndexOf('/', toPos-1);
+
+      String [] ret;
+      if(delimPos == -1)
+      {
+         ret = new String []
+         {
+            "",
+            pathName.substring(delimPos+1, toPos)
+         };
+      }
+      else
+      {
+         ret = new String []
+         {
+            pathName.substring(0, delimPos),
+            pathName.substring(delimPos+1, toPos)
+         };
+      }
+      return ret;
+   }
+
+   /**
+    * Temporary files naming scheme
+    *
+    * @param name the name
+    * @return random name
+    */
+   private static String getTempFileName(String name)
+   {
+      int delim = name.lastIndexOf("/");
+      if (delim != -1)
+         name = name.substring(delim+1);
+      return UUID.randomUUID().toString().substring(0, 8) + "_" + name;
+   }
+
+   /**
+    * Use VFS's temp directory and make 'vfs-nested.tmp' sub-directory inside it for our purposes
+    *
+    * @return temp dir
+    */
+   private static String getTempDir()
+   {
+      File dir = new File(AbstractCopyMechanism.getTempDirectory(), "vfs-nested.tmp");
+      return dir.toString();
+   }
+
+   /**
+    * Delete the contents of a temporary directory. Delete first-level files only, don't drill down.
+    */
+   private static void deleteTmpDirContents()
+   {
+      try
+      {
+         File tmpDir = new File(getTempDir());
+         File [] files = tmpDir.listFiles();
+         if (files != null && files.length > 0)
+         {            
+            for (File file : files)
+            {
+               if (file.isDirectory() == false && file.isHidden() == false)
+                  file.delete();
+            }
+         }
+      }
+      catch(Exception ignored)
+      {
+      }
+   }
+
+   /**
+    * <tt>PriviligedAction</tt> class for checking a system property
+    */
+   private static class CheckForceCopy implements PrivilegedAction<Boolean>
+   {
+      public Boolean run()
+      {
+         String forceString = System.getProperty(VFSUtils.FORCE_COPY_KEY, "false");
+         return Boolean.valueOf(forceString);
+      }
+   }
+
+   static enum InitializationStatus
+   {
+      NOT_INITIALIZED,
+      INITIALIZING,
+      INITIALIZED
+   }
+
+   private static class RealURLInfo
+   {
+      String rootURL;
+      String relativePath;
+
+      RealURLInfo(File file) throws MalformedURLException
+      {
+         String url = file.toURL().toExternalForm();
+         if (url.endsWith("/"))
+            url = url.substring(0, url.length()-1);
+         rootURL = "jar:" + url + "!/";
+      }
+
+      URL toURL() throws MalformedURLException
+      {
+         if (relativePath == null || relativePath.length() == 0)
+            return new URL(rootURL);
+
+         if (relativePath.startsWith("/"))
+            relativePath = relativePath.substring(1);
+
+         return new URL(rootURL + relativePath);
+      }
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,195 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.context.zip;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * Handler representing an individual file (ZipEntry) within ZipEntryContext
- *
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.0 $
- */
-public class ZipEntryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
-{
-   /** The url */
-   private URL url;
-
-   /** isLeaf */
-   private boolean isLeaf;
-
-   /** has it been initialized yet */
-   transient private boolean initialized;
-
-   /**
-    * Create a new ZipEntryHandler.
-    *
-    * @param context ZipEntryContext
-    * @param parent  parent within the same context
-    * @param name    name of this file within context
-    * @param isLeaf  true if this file should have a URL not ending with '/', false otherwise
-    * @throws IOException for any error
-    */
-   public ZipEntryHandler(ZipEntryContext context, AbstractVirtualFileHandler parent, String name, boolean isLeaf) throws IOException
-   {
-      super(context, parent, name);
-
-      this.isLeaf = isLeaf;
-      if(parent != null)
-      {
-         context.addChild(parent, this);
-      }
-   }
-
-   private synchronized void init()
-   {
-      if (initialized)
-         return;
-
-      StringBuilder vfsUrl = new StringBuilder();
-      try
-      {
-         url = getZipEntryContext().getChildURL(getParent(), getName());
-         String currentUrl = url.toString();
-         int pos = currentUrl.indexOf(":/");
-         vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
-
-         if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
-            vfsUrl.append("/");
-         setVfsUrl(new URL(vfsUrl.toString()));
-      }
-      catch(Exception ex)
-      {
-         throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
-      }
-      initialized = true;
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      init();
-      return VFSUtils.toURI(url);
-   }
-
-   public long getLastModified() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().getLastModified(this);
-   }
-
-   public long getSize() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().getSize(this);
-   }
-
-   public boolean exists() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().exists(this);
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().isLeaf(this);
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      checkClosed();
-      return false;
-   }
-
-   public boolean isNested() throws IOException
-   {
-      return ZipEntryContext.isNested(this);
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().openStream(this);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().getChildren(this, ignoreErrors);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      checkClosed();
-      return structuredFindChild(path);
-   }
-
-   public boolean removeChild(String name) throws IOException
-   {
-      return false;
-   }
-
-   public boolean delete(int gracePeriod) throws IOException
-   {
-      checkClosed();
-      boolean deleted = getZipEntryContext().delete(this, gracePeriod);
-      if (deleted)
-         super.delete(gracePeriod);
-
-      return deleted;
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      return getZipEntryContext().getChild(this, name);
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      if (original instanceof AbstractVirtualFileHandler == false)
-         throw new IllegalArgumentException("Original file handler not found in this context: " + original);
-
-      getZipEntryContext().replaceChild(this, (AbstractVirtualFileHandler) original, replacement);
-   }
-
-   private ZipEntryContext getZipEntryContext()
-   {
-      return ((ZipEntryContext) getLocalVFSContext());
-   }
-
-   public URL toVfsUrl()
-   {
-      init();
-      return super.getVfsUrl();
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,247 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * Handler representing an individual file (ZipEntry) within ZipEntryContext
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+public class ZipEntryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
+{
+   /** The url */
+   private URL url;
+
+   /** isLeaf */
+   private boolean isLeaf;
+
+   /** has it been initialized yet */
+   transient private boolean initialized;
+
+   /**
+    * Create a new ZipEntryHandler.
+    *
+    * @param context ZipEntryContext
+    * @param parent  parent within the same context
+    * @param name    name of this file within context
+    * @param isLeaf  true if this file should have a URL not ending with '/', false otherwise
+    * @throws IOException for any error
+    */
+   public ZipEntryHandler(ZipEntryContext context, AbstractVirtualFileHandler parent, String name, boolean isLeaf) throws IOException
+   {
+      super(context, parent, name);
+
+      this.isLeaf = isLeaf;
+      if(parent != null)
+      {
+         context.addChild(parent, this);
+      }
+   }
+
+   private synchronized void init()
+   {
+      if (initialized)
+         return;
+
+      StringBuilder vfsUrl = new StringBuilder();
+      try
+      {
+         url = getZipEntryContext().getChildURL(getParent(), getName());
+         String currentUrl = url.toString();
+         int pos = currentUrl.indexOf(":/");
+         vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
+
+         if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
+            vfsUrl.append("/");
+         setVfsUrl(new URL(vfsUrl.toString()));
+      }
+      catch(Exception ex)
+      {
+         throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
+      }
+      initialized = true;
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      init();
+      return VFSUtils.toURI(url);
+   }
+
+   public long getLastModified() throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().getLastModified(this);
+   }
+
+   public long getSize() throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().getSize(this);
+   }
+
+   public boolean exists() throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().exists(this);
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().isLeaf(this);
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      checkClosed();
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return ZipEntryContext.isNested(this);
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().openStream(this);
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      checkClosed();
+      return getZipEntryContext().getChildren(this, ignoreErrors);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      checkClosed();
+      return structuredFindChild(path);
+   }
+
+   public boolean removeChild(String name) throws IOException
+   {
+      return false;
+   }
+
+   public boolean delete(int gracePeriod) throws IOException
+   {
+      checkClosed();
+      boolean deleted = getZipEntryContext().delete(this, gracePeriod);
+      if (deleted)
+         super.delete(gracePeriod);
+
+      return deleted;
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      return getZipEntryContext().getChild(this, name);
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      if (original instanceof AbstractVirtualFileHandler == false)
+         throw new IllegalArgumentException("Original file handler not found in this context: " + original);
+
+      getZipEntryContext().replaceChild(this, (AbstractVirtualFileHandler) original, replacement);
+   }
+
+   private ZipEntryContext getZipEntryContext()
+   {
+      return ((ZipEntryContext) getLocalVFSContext());
+   }
+
+   public URL toVfsUrl()
+   {
+      init();
+      return super.getVfsUrl();
+   }
+
+   public URL getRealURL() throws IOException, URISyntaxException
+   {
+      // see how far the parent contexts go
+      // if there is no parent context or it is of type FileSystemContext
+      // ZipEntryContext -> jar!/
+      // ZipEntryContext / ZipEntryContext -> jar!/jar
+      // ZipEntryConteyt / ZipEntryContext / ZipEntryContext ... -> jar!/jar
+      VFSContext ctx = getLocalVFSContext();
+      VirtualFileHandler peer = getLocalVFSContext().getRootPeer();
+
+      if (peer == null)
+      {
+         URL ctxURL = getZipEntryContext().getRealURL();
+         String ctxURLStr = ctxURL.toExternalForm();
+         if (ctxURLStr.endsWith("!/"))
+         {
+            String lpath = getLocalPathName();
+            if (lpath.startsWith("/"))
+               lpath = lpath.substring(1);
+
+            if (lpath.length() == 0)
+               return ctxURL;
+            else
+               return new URL(ctxURLStr + lpath);
+         }
+         return ctxURL;
+      }
+
+      if (peer instanceof AbstractVirtualFileHandler
+         && ((AbstractVirtualFileHandler)peer).getLocalVFSContext() instanceof FileSystemContext)
+      {
+         String lpath = getLocalPathName();
+         if (lpath.startsWith("/") == false)
+            lpath = "/" + lpath;
+         return new URL("jar:file:" + ctx.getRootURI().getPath() + "!" + lpath);
+      }
+
+      if (peer instanceof AbstractVirtualFileHandler)
+      {
+         AbstractVirtualFileHandler aPeer =(AbstractVirtualFileHandler) peer;
+         URL realUrl = aPeer.getLocalVFSContext().getRoot().getRealURL();
+         String urlStr = realUrl.toExternalForm();
+         if (urlStr.endsWith("!/"))
+            return new URL(urlStr + aPeer.getLocalPathName());
+         else
+            return realUrl;
+      }
+       
+      throw new RuntimeException("Operation not supported for handler: " + this);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,244 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.copy;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URISyntaxException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.List;
-
-import org.jboss.logging.Logger;
-import org.jboss.util.id.GUID;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.plugins.context.DelegatingHandler;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * Copy mechanism to be used in VFSUtils.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class AbstractCopyMechanism implements CopyMechanism
-{
-   private static Logger log = Logger.getLogger(CopyMechanism.class);
-
-   private static File tempDir;
-
-   private static class GetTempDir implements PrivilegedAction<File>
-   {
-      public File run()
-      {
-         String tempDirKey = System.getProperty("vfs.temp.dir", "jboss.server.temp.dir");
-         return new File(System.getProperty(tempDirKey, System.getProperty("java.io.tmpdir")));
-      }
-   }
-
-   /**
-    * Get temp directory.
-    *
-    * @return the temp directory
-    */
-   public synchronized static File getTempDirectory()
-   {
-      if (tempDir == null)
-      {
-         tempDir = AccessController.doPrivileged(new GetTempDir());
-         log.info("VFS temp dir: " + tempDir);
-      }
-      return tempDir;
-   }
-
-   /**
-    * Get mechanism type.
-    *
-    * @return the type
-    */
-   protected abstract String getType();
-
-   /**
-    * Is handler already modified.
-    *
-    * @param handler the handler
-    * @return true if already modified
-    * @throws IOException for any error
-    */
-   protected abstract boolean isAlreadyModified(VirtualFileHandler handler) throws IOException;
-
-   /**
-    * Should we replace old handler with new.
-    *
-    * @param parent the parent handler
-    * @param oldHandler the old handler
-    * @param newHandler the new handler
-    * @return true if needs replacement
-    * @throws IOException for any error
-    */
-   protected abstract boolean replaceOldHandler(VirtualFileHandler parent, VirtualFileHandler oldHandler, VirtualFileHandler newHandler) throws IOException;
-
-   /**
-    * Unwrap the handler from possible delegate handler.
-    *
-    * @param handler the handler to unwrap
-    * @return unwrapped handler
-    */
-   protected VirtualFileHandler unwrap(VirtualFileHandler handler)
-   {
-      if (handler instanceof DelegatingHandler)
-         handler = ((DelegatingHandler)handler).getDelegate();
-      return handler;
-   }
-
-   public VirtualFile copy(VirtualFile file, VirtualFileHandler handler) throws IOException, URISyntaxException
-   {
-      VirtualFileHandler unwrapped = unwrap(handler);
-      // check modification on unwrapped
-      if (isAlreadyModified(unwrapped))
-      {
-         if (log.isTraceEnabled())
-            log.trace("Should already be " + getType() + ": " + unwrapped);
-         return file;
-      }
-
-      //create guid dir
-      File guidDir = createTempDirectory(getTempDirectory(), GUID.asString());
-      // unpack handler
-      File copy = copy(guidDir, handler);
-      // create new handler
-      FileSystemContext fileSystemContext = new FileSystemContext(copy);
-      VirtualFileHandler newHandler = fileSystemContext.getRoot();
-      VirtualFileHandler parent = handler.getParent();
-      if (parent != null && replaceOldHandler(parent, handler, newHandler))
-         parent.replaceChild(handler, newHandler);
-
-      return newHandler.getVirtualFile();
-   }
-
-   /**
-    * Copy handler.
-    *
-    * @param guidDir the guid directory
-    * @param handler the handler to copy
-    * @return handler's copy as file
-    * @throws IOException for any error
-    */
-   protected File copy(File guidDir, VirtualFileHandler handler) throws IOException
-   {
-      File copy = createTempDirectory(guidDir, handler.getName());
-      unpack(handler, copy, false);
-      return copy;
-   }
-
-   /**
-    * Create the temp directory.
-    *
-    * @param parent the parent
-    * @param name the dir name
-    * @return new directory
-    */
-   protected static File createTempDirectory(File parent, String name)
-   {
-      File file = new File(parent, name);
-      if (file.mkdir() == false)
-         throw new IllegalArgumentException("Cannot create directory: " + file);
-      file.deleteOnExit();
-      return file;
-   }
-
-   /**
-    * Unpack the root into file.
-    * Repeat this on the root's children.
-    *
-    * @param root the root
-    * @param file the file
-    * @param writeRoot do we write root
-    * @throws IOException for any error
-    */
-   protected static void unpack(VirtualFileHandler root, File file, boolean writeRoot) throws IOException
-   {
-      // should we write the root
-      if (writeRoot)
-         rewrite(root, file);
-
-      if (root.isLeaf() == false)
-      {
-         List<VirtualFileHandler> children = root.getChildren(true);
-         if (children != null && children.isEmpty() == false)
-         {
-            for (VirtualFileHandler handler : children)
-            {
-               File next = new File(file, handler.getName());
-               if (handler.isLeaf() == false && next.mkdir() == false)
-                  throw new IllegalArgumentException("Problems creating new directory: " + next);
-               next.deleteOnExit();
-
-               unpack(handler, next, handler.isLeaf());
-            }
-         }
-      }
-   }
-
-   /**
-    * Rewrite contents of handler into file.
-    *
-    * @param handler the handler
-    * @param file the file
-    * @throws IOException for any error
-    */
-   protected static void rewrite(VirtualFileHandler handler, File file) throws IOException
-   {
-      OutputStream out = new FileOutputStream(file);
-      InputStream in = handler.openStream();
-      try
-      {
-         byte[] bytes = new byte[1024];
-         while (in.available() > 0)
-         {
-            int length = in.read(bytes);
-            if (length > 0)
-               out.write(bytes, 0, length);
-         }
-      }
-      finally
-      {
-         try
-         {
-            in.close();
-         }
-         catch (IOException ignored)
-         {
-         }
-         try
-         {
-            out.close();
-         }
-         catch (IOException ignored)
-         {
-         }
-      }
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/copy/AbstractCopyMechanism.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,260 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.copy;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+import org.jboss.util.id.GUID;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.spi.ExceptionHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * Copy mechanism to be used in VFSUtils.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class AbstractCopyMechanism implements CopyMechanism
+{
+   private static Logger log = Logger.getLogger(CopyMechanism.class);
+
+   private static File tempDir;
+
+   private static class GetTempDir implements PrivilegedAction<File>
+   {
+      public File run()
+      {
+         String tempDirKey = System.getProperty("vfs.temp.dir", "jboss.server.temp.dir");
+         return new File(System.getProperty(tempDirKey, System.getProperty("java.io.tmpdir")));
+      }
+   }
+
+   /**
+    * Get temp directory.
+    *
+    * @return the temp directory
+    */
+   public synchronized static File getTempDirectory()
+   {
+      if (tempDir == null)
+      {
+         tempDir = AccessController.doPrivileged(new GetTempDir());
+         log.info("VFS temp dir: " + tempDir);
+      }
+      return tempDir;
+   }
+
+   /**
+    * Get mechanism type.
+    *
+    * @return the type
+    */
+   protected abstract String getType();
+
+   /**
+    * Is handler already modified.
+    *
+    * @param handler the handler
+    * @return true if already modified
+    * @throws IOException for any error
+    */
+   protected abstract boolean isAlreadyModified(VirtualFileHandler handler) throws IOException;
+
+   /**
+    * Should we replace old handler with new.
+    *
+    * @param parent the parent handler
+    * @param oldHandler the old handler
+    * @param newHandler the new handler
+    * @return true if needs replacement
+    * @throws IOException for any error
+    */
+   protected abstract boolean replaceOldHandler(VirtualFileHandler parent, VirtualFileHandler oldHandler, VirtualFileHandler newHandler) throws IOException;
+
+   /**
+    * Unwrap the handler from possible delegate handler.
+    *
+    * @param handler the handler to unwrap
+    * @return unwrapped handler
+    */
+   protected VirtualFileHandler unwrap(VirtualFileHandler handler)
+   {
+      if (handler instanceof DelegatingHandler)
+         handler = ((DelegatingHandler)handler).getDelegate();
+      return handler;
+   }
+
+   public VirtualFile copy(VirtualFile file, VirtualFileHandler handler) throws IOException, URISyntaxException
+   {
+      VirtualFileHandler unwrapped = unwrap(handler);
+      // check modification on unwrapped
+      if (isAlreadyModified(unwrapped))
+      {
+         if (log.isTraceEnabled())
+            log.trace("Should already be " + getType() + ": " + unwrapped);
+         return file;
+      }
+
+      //create guid dir
+      File guidDir = createTempDirectory(getTempDirectory(), GUID.asString());
+      // unpack handler
+      File copy = copy(guidDir, handler);
+      // create new handler
+      FileSystemContext fileSystemContext = new FileSystemContext(copy);
+
+      // merge old options
+      VFSContext oldVFSContext = handler.getVFSContext();
+      Map<String, String> newOptions = fileSystemContext.getOptions();
+      Map<String, String> oldOptions = oldVFSContext.getOptions();
+      if (newOptions != null && oldOptions != null && oldOptions.isEmpty() == false)
+         newOptions.putAll(oldOptions);
+
+      // copy exception handler
+      ExceptionHandler eh = oldVFSContext.getExceptionHandler();
+      if (eh != null)
+         fileSystemContext.setExceptionHandler(eh);
+
+      VirtualFileHandler newHandler = fileSystemContext.getRoot();
+      VirtualFileHandler parent = handler.getParent();
+      if (parent != null && replaceOldHandler(parent, handler, newHandler))
+         parent.replaceChild(handler, newHandler);
+
+      return newHandler.getVirtualFile();
+   }
+
+   /**
+    * Copy handler.
+    *
+    * @param guidDir the guid directory
+    * @param handler the handler to copy
+    * @return handler's copy as file
+    * @throws IOException for any error
+    */
+   protected File copy(File guidDir, VirtualFileHandler handler) throws IOException
+   {
+      File copy = createTempDirectory(guidDir, handler.getName());
+      unpack(handler, copy, false);
+      return copy;
+   }
+
+   /**
+    * Create the temp directory.
+    *
+    * @param parent the parent
+    * @param name the dir name
+    * @return new directory
+    */
+   protected static File createTempDirectory(File parent, String name)
+   {
+      File file = new File(parent, name);
+      if (file.mkdir() == false)
+         throw new IllegalArgumentException("Cannot create directory: " + file);
+      file.deleteOnExit();
+      return file;
+   }
+
+   /**
+    * Unpack the root into file.
+    * Repeat this on the root's children.
+    *
+    * @param root the root
+    * @param file the file
+    * @param writeRoot do we write root
+    * @throws IOException for any error
+    */
+   protected static void unpack(VirtualFileHandler root, File file, boolean writeRoot) throws IOException
+   {
+      // should we write the root
+      if (writeRoot)
+         rewrite(root, file);
+
+      if (root.isLeaf() == false)
+      {
+         List<VirtualFileHandler> children = root.getChildren(true);
+         if (children != null && children.isEmpty() == false)
+         {
+            for (VirtualFileHandler handler : children)
+            {
+               File next = new File(file, handler.getName());
+               if (handler.isLeaf() == false && next.mkdir() == false)
+                  throw new IllegalArgumentException("Problems creating new directory: " + next);
+               next.deleteOnExit();
+
+               unpack(handler, next, handler.isLeaf());
+            }
+         }
+      }
+   }
+
+   /**
+    * Rewrite contents of handler into file.
+    *
+    * @param handler the handler
+    * @param file the file
+    * @throws IOException for any error
+    */
+   protected static void rewrite(VirtualFileHandler handler, File file) throws IOException
+   {
+      OutputStream out = new FileOutputStream(file);
+      InputStream in = handler.openStream();
+      try
+      {
+         byte[] bytes = new byte[1024];
+         while (in.available() > 0)
+         {
+            int length = in.read(bytes);
+            if (length > 0)
+               out.write(bytes, 0, length);
+         }
+      }
+      finally
+      {
+         try
+         {
+            in.close();
+         }
+         catch (IOException ignored)
+         {
+         }
+         try
+         {
+            out.close();
+         }
+         catch (IOException ignored)
+         {
+         }
+      }
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,216 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.plugins.vfs.helpers;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * PathTokenizer.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @version $Revision: 1.1 $
- */
- at SuppressWarnings({"StringEquality"})
-public class PathTokenizer
-{
-   /** The reverse path const */
-   private static final String CURRENT_PATH = ".";
-
-   /** The reverse path const */
-   private static final String REVERSE_PATH = "..";
-
-   /**
-    * Utility class
-    */
-   private PathTokenizer()
-   {
-   }
-
-   /**
-    * Get the remaining path from some tokens
-    *
-    * @param tokens the tokens
-    * @param i the current location
-    * @param end the end index
-    * @return the remaining path
-    * @throws IllegalArgumentException for null tokens or i is out of range
-    */
-   protected static String getRemainingPath(List<String> tokens, int i, int end)
-   {
-      if (tokens == null)
-         throw new IllegalArgumentException("Null tokens");
-      if (i < 0 || i >= end)
-         throw new IllegalArgumentException("i is not in the range of tokens: 0-" + (end-1));
-
-      if (i == end-1)
-         return tokens.get(end-1);
-
-      StringBuilder buffer = new StringBuilder();
-      for (; i < end-1; ++i)
-      {
-         buffer.append(tokens.get(i));
-         buffer.append("/");
-      }
-      buffer.append(tokens.get(end-1));
-      return buffer.toString();
-   }
-
-   /**
-    * Get the tokens
-    * 
-    * @param path the path
-    * @return the tokens or null if the path is empty
-    * @throws IllegalArgumentException if the path is null, it is empty or it is a relative path
-    */
-   public static List<String> getTokens(String path)
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-
-      char[] chars = path.toCharArray();
-      StringBuilder buffer = new StringBuilder();
-      List<String> list = new ArrayList<String>();
-      String specialToken = null;
-
-      for (int index=0; index < chars.length; index++)
-      {
-         char ch = chars[index];
-
-         if (ch == '/')
-         {
-            if (index > 0)
-            {
-               if (buffer.length() == 0 && specialToken == null)
-                  continue;
-
-               if (specialToken != null)
-                  list.add(specialToken);
-               else
-                  list.add(buffer.toString());
-
-               // reset
-               buffer.setLength(0);
-               specialToken = null;
-            }
-         }
-         else if (ch == '.')
-         {
-            if (specialToken == null && buffer.length() == 0)
-               specialToken = CURRENT_PATH;
-            else if (specialToken == CURRENT_PATH && buffer.length() == 0)
-               specialToken = REVERSE_PATH;
-            else if (specialToken != null && buffer.length() == 0)
-               throw new IllegalArgumentException("Illegal token in path: " + path);
-            else
-               buffer.append(ch);
-         }
-         else
-         {
-            // token starts with '.' or '..', but also has some path after that
-            if (specialToken != null)
-               throw new IllegalArgumentException("Illegal token in path: " + path);
-
-            buffer.append(ch);
-         }
-      }
-
-      // add last token
-      if (specialToken != null)
-         list.add(specialToken);
-      else if (buffer.length() > 0)
-         list.add(buffer.toString());
-
-      return list;
-   }
-   
-   /**
-    * Get the remaining path from some tokens
-    * 
-    * @param tokens the tokens
-    * @param i the current location
-    * @return the remaining path
-    * @throws IllegalArgumentException for null tokens or i is out of range
-    */
-   public static String getRemainingPath(List<String> tokens, int i)
-   {
-      if (tokens == null)
-         throw new IllegalArgumentException("Null tokens");
-
-      return getRemainingPath(tokens, i, tokens.size());
-   }
-
-   /**
-    * Apply any . or .. paths in the path param.
-    *
-    * @param path the path
-    * @return simple path, containing no . or .. paths
-    * @throws IOException if reverse path goes over the top path
-    */
-   public static String applySpecialPaths(String path) throws IOException
-   {
-      List<String> tokens = getTokens(path);
-      if (tokens == null)
-         return null;
-
-      int i = 0;
-      for(int j = 0; j < tokens.size(); j++)
-      {
-         String token = tokens.get(j);
-
-         if (isCurrentToken(token))
-            continue;
-         else if (isReverseToken(token))
-            i--;
-         else
-            tokens.set(i++, token);
-
-         if (i < 0)
-            throw new IOException("Using reverse path on top path: " + path);
-      }
-      return getRemainingPath(tokens, 0, i);
-   }
-
-   /**
-    * Is current token.
-    *
-    * @param token the token to check
-    * @return true if token matches current path token
-    */
-   public static boolean isCurrentToken(String token)
-   {
-      return CURRENT_PATH == token;
-   }
-
-   /**
-    * Is reverse token.
-    *
-    * @param token the token to check
-    * @return true if token matches reverse path token
-    */
-   public static boolean isReverseToken(String token)
-   {
-      return REVERSE_PATH == token;
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,252 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.vfs.helpers;
+
+import java.io.IOException;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * PathTokenizer.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 1.1 $
+ */
+ at SuppressWarnings({"StringEquality"})
+public class PathTokenizer
+{
+   /** The reverse path const */
+   private static final String CURRENT_PATH = ".";
+
+   /** The reverse path const */
+   private static final String REVERSE_PATH = "..";
+
+   /** Catch some suspicious tokens */
+   private static boolean errorOnSuspiciousTokens;
+
+   /** Flag permission */
+   private static Permission flagPermission = new RuntimePermission(PathTokenizer.class.getName() + ".setErrorOnSuspiciousTokens");
+
+   /**
+    * Utility class
+    */
+   private PathTokenizer()
+   {
+   }
+
+   /**
+    * Get the remaining path from some tokens
+    *
+    * @param tokens the tokens
+    * @param i the current location
+    * @param end the end index
+    * @return the remaining path
+    * @throws IllegalArgumentException for null tokens or i is out of range
+    */
+   protected static String getRemainingPath(List<String> tokens, int i, int end)
+   {
+      if (tokens == null)
+         throw new IllegalArgumentException("Null tokens");
+      if (i < 0 || i >= end)
+         throw new IllegalArgumentException("i is not in the range of tokens: 0-" + (end-1));
+
+      if (i == end-1)
+         return tokens.get(end-1);
+
+      StringBuilder buffer = new StringBuilder();
+      for (; i < end-1; ++i)
+      {
+         buffer.append(tokens.get(i));
+         buffer.append("/");
+      }
+      buffer.append(tokens.get(end-1));
+      return buffer.toString();
+   }
+
+   /**
+    * Get the tokens
+    * 
+    * @param path the path
+    * @return the tokens or null if the path is empty
+    * @throws IllegalArgumentException if the path is null, it is empty or it is a relative path
+    */
+   public static List<String> getTokens(String path)
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+
+      char[] chars = path.toCharArray();
+      StringBuilder buffer = new StringBuilder();
+      List<String> list = new ArrayList<String>();
+      String specialToken = null;
+
+      for (int index=0; index < chars.length; index++)
+      {
+         char ch = chars[index];
+
+         if (ch == '/')
+         {
+            if (index > 0)
+            {
+               if (buffer.length() == 0 && specialToken == null)
+                  continue;
+
+               if (specialToken != null)
+                  list.add(specialToken);
+               else
+                  list.add(buffer.toString());
+
+               // reset
+               buffer.setLength(0);
+               specialToken = null;
+            }
+         }
+         else if (ch == '.')
+         {
+            int bufferLength = buffer.length();
+
+            if (specialToken == null && bufferLength == 0)
+               specialToken = CURRENT_PATH;
+            else if (specialToken == CURRENT_PATH && bufferLength == 0)
+               specialToken = REVERSE_PATH;
+            else if (specialToken == REVERSE_PATH && bufferLength == 0)
+            {
+               if (errorOnSuspiciousTokens)
+                  throw new IllegalArgumentException("Illegal token (" + specialToken + ch + ") in path: " + path);
+
+               buffer.append(specialToken).append(ch);
+               specialToken = null;
+            }
+            else
+               buffer.append(ch);
+         }
+         else
+         {
+            // token starts with '.' or '..', but also has some path after that
+            if (specialToken != null)
+            {
+               // we don't allow tokens after '..'
+               if (errorOnSuspiciousTokens && specialToken == REVERSE_PATH)
+                  throw new IllegalArgumentException("Illegal token (" + specialToken + ch + ") in path: " + path);
+
+               // after '.' more path is legal == unix hidden directories
+               buffer.append(specialToken);
+               specialToken = null;
+            }
+            buffer.append(ch);
+         }
+      }
+
+      // add last token
+      if (specialToken != null)
+         list.add(specialToken);
+      else if (buffer.length() > 0)
+         list.add(buffer.toString());
+
+      return list;
+   }
+   
+   /**
+    * Get the remaining path from some tokens
+    * 
+    * @param tokens the tokens
+    * @param i the current location
+    * @return the remaining path
+    * @throws IllegalArgumentException for null tokens or i is out of range
+    */
+   public static String getRemainingPath(List<String> tokens, int i)
+   {
+      if (tokens == null)
+         throw new IllegalArgumentException("Null tokens");
+
+      return getRemainingPath(tokens, i, tokens.size());
+   }
+
+   /**
+    * Apply any . or .. paths in the path param.
+    *
+    * @param path the path
+    * @return simple path, containing no . or .. paths
+    * @throws IOException if reverse path goes over the top path
+    */
+   public static String applySpecialPaths(String path) throws IOException
+   {
+      List<String> tokens = getTokens(path);
+      if (tokens == null)
+         return null;
+
+      int i = 0;
+      for(int j = 0; j < tokens.size(); j++)
+      {
+         String token = tokens.get(j);
+
+         if (isCurrentToken(token))
+            continue;
+         else if (isReverseToken(token))
+            i--;
+         else
+            tokens.set(i++, token);
+
+         if (i < 0)
+            throw new IOException("Using reverse path on top path: " + path);
+      }
+      return getRemainingPath(tokens, 0, i);
+   }
+
+   /**
+    * Is current token.
+    *
+    * @param token the token to check
+    * @return true if token matches current path token
+    */
+   public static boolean isCurrentToken(String token)
+   {
+      return CURRENT_PATH == token;
+   }
+
+   /**
+    * Is reverse token.
+    *
+    * @param token the token to check
+    * @return true if token matches reverse path token
+    */
+   public static boolean isReverseToken(String token)
+   {
+      return REVERSE_PATH == token;
+   }
+
+   /**
+    * Set errorOnSuspiciousTokens flag.
+    *
+    * @param errorOnSuspiciousTokens the errorOnSuspiciousTokens flag
+    */
+   public static void setErrorOnSuspiciousTokens(boolean errorOnSuspiciousTokens)
+   {
+      SecurityManager sm = System.getSecurityManager();
+      if (sm != null)
+         sm.checkPermission(flagPermission);
+      
+      PathTokenizer.errorOnSuspiciousTokens = errorOnSuspiciousTokens;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,106 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.protocol;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLDecoder;
-import java.net.URLStreamHandler;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-import org.jboss.virtual.plugins.vfs.VirtualFileURLConnection;
-
-/**
- * VFS's file URL handler.
- *
- * @author <a href="bill at jboss.com">Bill Burke</a>
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class AbstractVFSHandler extends URLStreamHandler
-{
-   private static Map<Class, Integer> lengths = new WeakHashMap<Class, Integer>();
-
-   /**
-    * Get protocol name length.
-    * e.g. vfsfile - 7, vfszip - 6, ...
-    *
-    * @return
-    */
-   protected int getProtocolNameLength()
-   {
-      Class<?> clazz = getClass();
-      Integer length = lengths.get(clazz);
-      if (length == null)
-      {
-         Package pck = clazz.getPackage();
-         String pckName = pck.getName();
-         int p = pckName.lastIndexOf('.');
-         length = pckName.substring(p + 1).length();
-         lengths.put(clazz, length);
-      }
-      return length;
-   }
-
-   protected URLConnection openConnection(URL url) throws IOException
-   {
-      String file = URLDecoder.decode(url.toExternalForm(), "UTF-8").substring(getProtocolNameLength() + 1); // strip out vfs protocol + :
-      URL vfsurl = null;
-      String relative;
-      String queryStr = url.getQuery();
-      if (queryStr != null)
-         file = file.substring(0, file.lastIndexOf('?'));
-
-      File fp = new File(file);
-      if (fp.exists())
-      {
-         vfsurl = fp.getParentFile().toURL();
-         relative = fp.getName();
-      }
-      else
-      {
-         File curr = fp;
-         relative = fp.getName();
-         while ((curr = curr.getParentFile()) != null)
-         {
-            if (curr.exists())
-            {
-               vfsurl = curr.toURL();
-               break;
-            }
-            else
-            {
-               relative = curr.getName() + "/" + relative;
-            }
-         }
-      }
-
-      if (vfsurl == null)
-         throw new IOException("VFS file does not exist: " + url);
-      if (queryStr != null)
-         vfsurl = new URL(vfsurl + "?" + queryStr);
-      
-      return new VirtualFileURLConnection(url, vfsurl, relative);
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/protocol/AbstractVFSHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,114 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.protocol;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.net.URLStreamHandler;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.vfs.VirtualFileURLConnection;
+import org.jboss.virtual.spi.cache.VFSCache;
+import org.jboss.virtual.spi.cache.VFSCacheFactory;
+
+/**
+ * VFS's file URL handler.
+ *
+ * @author <a href="bill at jboss.com">Bill Burke</a>
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class AbstractVFSHandler extends URLStreamHandler
+{
+   private static Map<Class, Integer> lengths = new WeakHashMap<Class, Integer>();
+
+   /**
+    * Get protocol name length.
+    * e.g. vfsfile - 7, vfszip - 6, ...
+    *
+    * @return protocol name lenght
+    */
+   protected int getProtocolNameLength()
+   {
+      Class<?> clazz = getClass();
+      Integer length = lengths.get(clazz);
+      if (length == null)
+      {
+         Package pck = clazz.getPackage();
+         String pckName = pck.getName();
+         int p = pckName.lastIndexOf('.');
+         length = pckName.substring(p + 1).length();
+         lengths.put(clazz, length);
+      }
+      return length;
+   }
+
+   protected URLConnection openConnection(URL url) throws IOException
+   {
+      VFSCache cache = VFSCacheFactory.getInstance();
+      VirtualFile vf = cache.getFile(url);
+      if (vf != null)
+         return new VirtualFileURLConnection(url, vf);
+
+      String file = URLDecoder.decode(url.toExternalForm(), "UTF-8").substring(getProtocolNameLength() + 1); // strip out vfs protocol + :
+      URL vfsurl = null;
+      String relative;
+      String queryStr = url.getQuery();
+      if (queryStr != null)
+         file = file.substring(0, file.lastIndexOf('?'));
+
+      File fp = new File(file);
+      if (fp.exists())
+      {
+         vfsurl = fp.getParentFile().toURL();
+         relative = fp.getName();
+      }
+      else
+      {
+         File curr = fp;
+         relative = fp.getName();
+         while ((curr = curr.getParentFile()) != null)
+         {
+            if (curr.exists())
+            {
+               vfsurl = curr.toURL();
+               break;
+            }
+            else
+            {
+               relative = curr.getName() + "/" + relative;
+            }
+         }
+      }
+
+      if (vfsurl == null)
+         throw new IOException("VFS file does not exist: " + url);
+      if (queryStr != null)
+         vfsurl = new URL(vfsurl + "?" + queryStr);
+      
+      return new VirtualFileURLConnection(url, vfsurl, relative);
+   }
+}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/ExceptionHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/ExceptionHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/ExceptionHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/ExceptionHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,48 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.spi;
+
+/**
+ * VFS exception handler.
+ *
+ * Custom exception handling methods shoud be added here
+ * and used at the pointcut where exception is thrown.
+ *
+ * Its abstract super class should implement them all
+ * hence back compatibility is assured by noop.
+ *
+ * Real handlers should just override some methods that
+ * they know how to handle. 
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public interface ExceptionHandler
+{
+   /**
+    * Handle zip entries initializaion exception.
+    *
+    * @param e the cause exception
+    * @param name the file name
+    * @throws RuntimeException if not handled
+    */
+   void handleZipEntriesInitException(Exception e, String name);
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/VFSContext.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,116 +0,0 @@
-/*
-  * JBoss, Home of Professional Open Source
-  * Copyright 2005, JBoss Inc., and individual contributors as indicated
-  * by the @authors tag. See the copyright.txt in the distribution for a
-  * full listing of individual contributors.
-  *
-  * This is free software; you can redistribute it and/or modify it
-  * under the terms of the GNU Lesser General Public License as
-  * published by the Free Software Foundation; either version 2.1 of
-  * the License, or (at your option) any later version.
-  *
-  * This software is distributed in the hope that it will be useful,
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  * Lesser General Public License for more details.
-  *
-  * You should have received a copy of the GNU Lesser General Public
-  * License along with this software; if not, write to the Free
-  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-  */
-package org.jboss.virtual.spi;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.virtual.VFS;
-
-/** 
- * A virtual file context
- * 
- * @author Scott.Stark at jboss.org
- * @author adrian at jboss.org
- * @author ales.justin at jboss.org
- * @version $Revision: 55466 $
- */
-public interface VFSContext
-{
-   /**
-    * Get the name.
-    *
-    * @return the name
-    */
-   String getName();
-
-   /**
-    * Get the root uri
-    * 
-    * @return the root uri
-    */
-   URI getRootURI();
-
-   /**
-    * Get the VFS for this context
-    * 
-    * @return the vfs
-    */
-   VFS getVFS();
-   
-   /**
-    * Return the root virtual file
-    * 
-    * @return the root
-    * @throws IOException for any problem accessing the VFS
-    */
-   VirtualFileHandler getRoot() throws IOException;
-
-   /**
-    * Return the peer representing the root of this context within another context.
-    * Used when mounting contexts within other contexts
-    *
-    * @return the root peer
-    */
-   VirtualFileHandler getRootPeer();
-
-   /**
-    * Get the context option settings
-    * 
-    * @return a map of the context options
-    */
-   Map<String, String> getOptions();
-
-   /**
-    * Get the children
-    * 
-    * @param parent the parent
-    * @param ignoreErrors whether to ignore errors
-    * @return the children
-    * @throws IOException for any problem accessing the VFS
-    * @throws IllegalArgumentException for a null parent
-    */
-   List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException;
-   
-   /**
-    * Get a child
-    *
-    * @param parent the parent
-    * @param path the path
-    * @return the child or <code>null</code> if not found
-    * @throws IOException for any problem accessing the VFS
-    * @throws IllegalArgumentException for a null parent or name
-    */
-   VirtualFileHandler getChild(VirtualFileHandler parent, String path) throws IOException;
-
-   /**
-    * Visit the virtual file system
-    * 
-    * @param handler the reference handler
-    * @param visitor the visitor
-    * @throws IOException for any error
-    * @throws IllegalArgumentException if the handler or visitor is null
-    */
-   void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor) throws IOException;
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/VFSContext.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VFSContext.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,130 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.virtual.spi;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.virtual.VFS;
+
+/** 
+ * A virtual file context
+ * 
+ * @author Scott.Stark at jboss.org
+ * @author adrian at jboss.org
+ * @author ales.justin at jboss.org
+ * @version $Revision: 55466 $
+ */
+public interface VFSContext
+{
+   /**
+    * Get the name.
+    *
+    * @return the name
+    */
+   String getName();
+
+   /**
+    * Get the root uri
+    * 
+    * @return the root uri
+    */
+   URI getRootURI();
+
+   /**
+    * Get the VFS for this context
+    * 
+    * @return the vfs
+    */
+   VFS getVFS();
+   
+   /**
+    * Return the root virtual file
+    * 
+    * @return the root
+    * @throws IOException for any problem accessing the VFS
+    */
+   VirtualFileHandler getRoot() throws IOException;
+
+   /**
+    * Return the peer representing the root of this context within another context.
+    * Used when mounting contexts within other contexts
+    *
+    * @return the root peer
+    */
+   VirtualFileHandler getRootPeer();
+
+   /**
+    * Get the context option settings
+    * 
+    * @return a map of the context options
+    */
+   Map<String, String> getOptions();
+
+   /**
+    * Get the children
+    * 
+    * @param parent the parent
+    * @param ignoreErrors whether to ignore errors
+    * @return the children
+    * @throws IOException for any problem accessing the VFS
+    * @throws IllegalArgumentException for a null parent
+    */
+   List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException;
+   
+   /**
+    * Get a child
+    *
+    * @param parent the parent
+    * @param path the path
+    * @return the child or <code>null</code> if not found
+    * @throws IOException for any problem accessing the VFS
+    * @throws IllegalArgumentException for a null parent or name
+    */
+   VirtualFileHandler getChild(VirtualFileHandler parent, String path) throws IOException;
+
+   /**
+    * Visit the virtual file system
+    * 
+    * @param handler the reference handler
+    * @param visitor the visitor
+    * @throws IOException for any error
+    * @throws IllegalArgumentException if the handler or visitor is null
+    */
+   void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor) throws IOException;
+
+   /**
+    * Get the exception handler.
+    *
+    * @return the exception handler
+    */
+   ExceptionHandler getExceptionHandler();
+
+   /**
+    * Set exception handler.
+    *
+    * @param exceptionHandler the exception handler.
+    */
+   void setExceptionHandler(ExceptionHandler exceptionHandler);
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,239 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2005, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.virtual.spi;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-
-import org.jboss.virtual.VirtualFile;
-
-/**
- * A virtual file handler
- * 
- * @author Scott.Stark at jboss.org
- * @author Adrian.Brock
- * @version $Revision: 44334 $
- */
-public interface VirtualFileHandler extends Serializable
-{
-   /**
-    * Get the simple VF name (X.java)
-    * 
-    * @return the simple file name
-    */
-   String getName();
-
-   /**
-    * Get the VFS relative path name (org/jboss/X.java)
-    * 
-    * @return the VFS relative path name
-    */
-   String getPathName();
-
-   /**
-    * Get the VFS local path name.
-    * Relative to root.
-    *
-    * @return the VFS local path name
-    */
-   String getLocalPathName();
-
-   /**
-    * Get a VFS-based URL
-    *
-    * @return the url
-    * @throws URISyntaxException for an error parsing the URI
-    * @throws MalformedURLException for any error
-    */
-   URL toVfsUrl() throws MalformedURLException, URISyntaxException;
-   
-
-   /**
-    * Get the VF URI (file://root/org/jboss/X.java)
-    * 
-    * @return the full URI to the VF in the VFS.
-    * @throws URISyntaxException for an error parsing the URI 
-    */
-   URI toURI() throws URISyntaxException;
-
-   /**
-    * Get the VF URL (file://root/org/jboss/X.java)
-    * 
-    * @return the full URL to the VF in the VFS.
-    * @throws URISyntaxException for an error parsing the URI 
-    * @throws MalformedURLException for any error
-    */
-   URL toURL() throws MalformedURLException, URISyntaxException;
-
-   /**
-    * When the file was last modified
-    * 
-    * @return the last modified time
-    * @throws IOException for any problem accessing the virtual file system
-    * @throws IllegalStateException if closed
-    */
-   long getLastModified() throws IOException;
-
-   /**
-    * Returns true if the file has been modified since this method was last called
-    * Last modified time is initialized at handler instantiation.
-    *
-    * @return true if modified, false otherwise
-    * @throws IOException for any error
-    */
-   boolean hasBeenModified() throws IOException;
-   
-   /**
-    * Get the size
-    * 
-    * @return the size
-    * @throws IOException for any problem accessing the virtual file system
-    * @throws IllegalStateException if closed
-    */
-   long getSize() throws IOException;
-
-   /**
-    * Tests whether the underlying implementation file still exists.
-    * @return true if the file exists, false otherwise.
-    * @throws IOException - thrown on failure to detect existence.
-    */
-   boolean exists() throws IOException;
-
-   /**
-    * Whether it is a simple leaf of the VFS,
-    * i.e. whether it can contain other files
-    * 
-    * @return true if a simple file.
-    * @throws IOException for any problem accessing the virtual file system
-    * @throws IllegalStateException if the file is closed
-    */
-   boolean isLeaf() throws IOException;
-   
-   /**
-    * Whether it is hidden
-    * 
-    * @return true if hidden.
-    * @throws IOException for any problem accessing the virtual file system
-    * @throws IllegalStateException if closed
-    */
-   boolean isHidden() throws IOException;
-
-   /**
-    * Access the file contents.
-    * 
-    * @return An InputStream for the file contents.
-    * @throws IOException for any problem accessing the virtual file system
-    * @throws IllegalStateException if closed
-    */
-   InputStream openStream() throws IOException;
-
-   /**
-    * Get the parent
-    * 
-    * @return the parent
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalStateException if closed
-    */
-   VirtualFileHandler getParent() throws IOException;
-
-   /**
-    * Get the children
-    * 
-    * @param ignoreErrors whether to ignore errors
-    * @return the children
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalStateException if closed
-    */
-   List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException;
-
-   /**
-    * Get a child
-    *
-    * @param path the path
-    * @return the child or <code>null</code> if not found
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalStateException if closed
-    */
-   VirtualFileHandler getChild(String path) throws IOException;
-
-   /**
-    * Remove a child
-    *
-    * @param name child name
-    * @return true if child was removed, false otherwise
-    * @throws IllegalStateException if closed
-    * @throws IOException if an error occurs
-    */
-   boolean removeChild(String name) throws IOException;
-
-   /**
-    * Get the VFSContext this file belongs to
-    * 
-    * @return the context
-    * @throws IllegalStateException if closed
-    */
-   VFSContext getVFSContext();
-
-   /**
-    * Get the virtual file wrapper
-    * 
-    * @return the wrapper
-    * @throws IllegalStateException if closed
-    */
-   VirtualFile getVirtualFile();
-   
-   /**
-    * Close the resources
-    */
-   void close();
-
-   /**
-    * Replace child.
-    *
-    * @param original the original
-    * @param replacement the replacement
-    */
-   void replaceChild(VirtualFileHandler original, VirtualFileHandler replacement);
-
-   /**
-    * Are we nested in some archive.
-    *
-    * @return true if this is archive entry
-    * @throws IOException for any error
-    */
-   boolean isNested() throws IOException;
-
-   /**
-    *  Delete a file represented by this handler
-    *
-    *  @param gracePeriod max time to wait for locks (in milliseconds)
-    *  @return boolean true if file was deleted, false otherwise
-    *  @throws IOException for any error
-    */
-   public boolean delete(int gracePeriod) throws IOException;
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,255 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.virtual.spi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.jboss.virtual.VirtualFile;
+
+/**
+ * A virtual file handler
+ * 
+ * @author Scott.Stark at jboss.org
+ * @author Adrian.Brock
+ * @version $Revision: 44334 $
+ */
+public interface VirtualFileHandler extends Serializable
+{
+   /**
+    * Get the simple VF name (X.java)
+    * 
+    * @return the simple file name
+    */
+   String getName();
+
+   /**
+    * Get the VFS relative path name (org/jboss/X.java)
+    * 
+    * @return the VFS relative path name
+    */
+   String getPathName();
+
+   /**
+    * Get the VFS local path name.
+    * Relative to root.
+    *
+    * @return the VFS local path name
+    */
+   String getLocalPathName();
+
+   /**
+    * Get a VFS-based URL
+    *
+    * @return the url
+    * @throws URISyntaxException for an error parsing the URI
+    * @throws MalformedURLException for any error
+    */
+   URL toVfsUrl() throws MalformedURLException, URISyntaxException;
+   
+   /**
+    * Get a file: or jar:file: URL representing a resource as precisely as possible.
+    * file: urls can represent files in the file system  (i.e.: file:/classes/MyClass.class)
+    * jar:file: urls can represent entries within zip archives in the filesystem
+    * (i.e.: jar:file:/lib/classes.jar!/MyClass.class)
+    * There is no standard URL handler to represent entries within archives that are themselves
+    * entries within archives.
+    * (i.e.: this doesn't work: jar:file:/lib/app.ear!/classes.jar!/MyClass.class
+    * In this case the most precise supported resource locator is: jar:file:/lib/app.ear!/classes.jar
+    * )
+    *
+    * @return the url
+    * @throws URISyntaxException for an error parsing the URI
+    * @throws MalformedURLException for any error constructing the URL
+    */
+   URL getRealURL() throws IOException, URISyntaxException;
+
+   /**
+    * Get the VF URI (file://root/org/jboss/X.java)
+    * 
+    * @return the full URI to the VF in the VFS.
+    * @throws URISyntaxException for an error parsing the URI 
+    */
+   URI toURI() throws URISyntaxException;
+
+   /**
+    * Get the VF URL (file://root/org/jboss/X.java)
+    * 
+    * @return the full URL to the VF in the VFS.
+    * @throws URISyntaxException for an error parsing the URI 
+    * @throws MalformedURLException for any error
+    */
+   URL toURL() throws MalformedURLException, URISyntaxException;
+
+   /**
+    * When the file was last modified
+    * 
+    * @return the last modified time
+    * @throws IOException for any problem accessing the virtual file system
+    * @throws IllegalStateException if closed
+    */
+   long getLastModified() throws IOException;
+
+   /**
+    * Returns true if the file has been modified since this method was last called
+    * Last modified time is initialized at handler instantiation.
+    *
+    * @return true if modified, false otherwise
+    * @throws IOException for any error
+    */
+   boolean hasBeenModified() throws IOException;
+   
+   /**
+    * Get the size
+    * 
+    * @return the size
+    * @throws IOException for any problem accessing the virtual file system
+    * @throws IllegalStateException if closed
+    */
+   long getSize() throws IOException;
+
+   /**
+    * Tests whether the underlying implementation file still exists.
+    * @return true if the file exists, false otherwise.
+    * @throws IOException - thrown on failure to detect existence.
+    */
+   boolean exists() throws IOException;
+
+   /**
+    * Whether it is a simple leaf of the VFS,
+    * i.e. whether it can contain other files
+    * 
+    * @return true if a simple file.
+    * @throws IOException for any problem accessing the virtual file system
+    * @throws IllegalStateException if the file is closed
+    */
+   boolean isLeaf() throws IOException;
+   
+   /**
+    * Whether it is hidden
+    * 
+    * @return true if hidden.
+    * @throws IOException for any problem accessing the virtual file system
+    * @throws IllegalStateException if closed
+    */
+   boolean isHidden() throws IOException;
+
+   /**
+    * Access the file contents.
+    * 
+    * @return An InputStream for the file contents.
+    * @throws IOException for any problem accessing the virtual file system
+    * @throws IllegalStateException if closed
+    */
+   InputStream openStream() throws IOException;
+
+   /**
+    * Get the parent
+    * 
+    * @return the parent
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalStateException if closed
+    */
+   VirtualFileHandler getParent() throws IOException;
+
+   /**
+    * Get the children
+    * 
+    * @param ignoreErrors whether to ignore errors
+    * @return the children
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalStateException if closed
+    */
+   List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException;
+
+   /**
+    * Get a child
+    *
+    * @param path the path
+    * @return the child or <code>null</code> if not found
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalStateException if closed
+    */
+   VirtualFileHandler getChild(String path) throws IOException;
+
+   /**
+    * Remove a child
+    *
+    * @param name child name
+    * @return true if child was removed, false otherwise
+    * @throws IllegalStateException if closed
+    * @throws IOException if an error occurs
+    */
+   boolean removeChild(String name) throws IOException;
+
+   /**
+    * Get the VFSContext this file belongs to
+    * 
+    * @return the context
+    * @throws IllegalStateException if closed
+    */
+   VFSContext getVFSContext();
+
+   /**
+    * Get the virtual file wrapper
+    * 
+    * @return the wrapper
+    * @throws IllegalStateException if closed
+    */
+   VirtualFile getVirtualFile();
+   
+   /**
+    * Close the resources
+    */
+   void close();
+
+   /**
+    * Replace child.
+    *
+    * @param original the original
+    * @param replacement the replacement
+    */
+   void replaceChild(VirtualFileHandler original, VirtualFileHandler replacement);
+
+   /**
+    * Are we nested in some archive.
+    *
+    * @return true if this is archive entry
+    * @throws IOException for any error
+    */
+   boolean isNested() throws IOException;
+
+   /**
+    *  Delete a file represented by this handler
+    *
+    *  @param gracePeriod max time to wait for locks (in milliseconds)
+    *  @return boolean true if file was deleted, false otherwise
+    *  @throws IOException for any error
+    */
+   public boolean delete(int gracePeriod) throws IOException;
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,86 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.spi.cache;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * Simple vfs cache interface.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public interface VFSCache
-{
-   /**
-    * Get the file.
-    *
-    * @param uri the file's uri
-    * @return virtual file instance
-    * @throws IOException for any error
-    */
-   VirtualFile getFile(URI uri) throws IOException;
-
-   /**
-    * Get the file.
-    *
-    * @param url the file's url
-    * @return virtual file instance
-    * @throws IOException for any error
-    */
-   VirtualFile getFile(URL url) throws IOException;
-
-   /**
-    * Put vfs context to cache.
-    *
-    * @param context the vfs context
-    */
-   void putContext(VFSContext context);
-
-   /**
-    * Remove vfs context from cache.
-    *
-    * @param context the vfs context
-    */
-   void removeContext(VFSContext context);
-
-   /**
-    * Start the cache.
-    *
-    * @throws Exception for any error
-    */
-   void start() throws Exception;
-
-   /**
-    * Stop the cache.
-    */
-   void stop();
-
-   /**
-    * Flush the cache.
-    */
-   void flush();
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,90 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.spi.cache;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * Simple vfs cache interface.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public interface VFSCache
+{
+   /**
+    * Get the file.
+    * Check the cache for cached entry,
+    * return null if no matching entry exists.
+    *
+    * @param uri the file's uri
+    * @return virtual file instance or null if it doesn't exist in cache
+    * @throws IOException for any error
+    */
+   VirtualFile getFile(URI uri) throws IOException;
+
+   /**
+    * Get the file.
+    * Check the cache for cached entry,
+    * return null if no matching entry exists.
+    *
+    * @param url the file's url
+    * @return virtual file instance or null if it doesn't exist in cache
+    * @throws IOException for any error
+    */
+   VirtualFile getFile(URL url) throws IOException;
+
+   /**
+    * Put vfs context to cache.
+    *
+    * @param context the vfs context
+    */
+   void putContext(VFSContext context);
+
+   /**
+    * Remove vfs context from cache.
+    *
+    * @param context the vfs context
+    */
+   void removeContext(VFSContext context);
+
+   /**
+    * Start the cache.
+    *
+    * @throws Exception for any error
+    */
+   void start() throws Exception;
+
+   /**
+    * Stop the cache.
+    */
+   void stop();
+
+   /**
+    * Flush the cache.
+    */
+   void flush();
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,135 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.spi.cache;
-
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import org.jboss.logging.Logger;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.spi.cache.helpers.NoopVFSCache;
-
-/**
- * Simple vfs cache factory.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- * @author Scott.Stark at jboss.org
- * @version $Revision$
- */
-public class VFSCacheFactory
-{
-   private static final Object lock = new Object();
-   private static Logger log = Logger.getLogger(VFSCacheFactory.class);
-
-   private static VFSCache instance;
-
-   private VFSCacheFactory()
-   {
-   }
-
-   /**
-    * Get VFS cache instance.
-    *
-    * @return the vfs cache instance
-    */
-   public static VFSCache getInstance()
-   {
-      return getInstance(null);
-   }
-   /**
-    * 
-    * Get VFS cache instance.
-    *
-    * @param defaultCacheImpl - the possibly null name of the VFSCache
-    * implementation to use. If null, the {@linkplain VFSUtils.VFS_CACHE_KEY}
-    * system property will be used.
-    * 
-    * @return the vfs cache instance
-    */
-   public static VFSCache getInstance(String defaultCacheImpl)
-   {
-      if (instance == null)
-      {
-         synchronized (lock)
-         {
-            if (instance == null)
-               instance = AccessController.doPrivileged(new VFSCacheCreatorAction(defaultCacheImpl));
-         }
-      }
-      return instance;
-   }
-
-   /**
-    * Set instance.
-    *
-    * This should be used with care.
-    * Better to leave it to getInstance method creation.
-    *
-    * @param cache cache instance to set
-    */
-   public static void setInstance(VFSCache cache)
-   {
-      if (cache != null && instance != null && instance instanceof NoopVFSCache == false)
-         throw new IllegalArgumentException("Instance already set!");
-
-      instance = cache;
-   }
-
-   private static class VFSCacheCreatorAction implements PrivilegedAction<VFSCache>
-   {
-      private String defaultCacheImpl;
-      VFSCacheCreatorAction(String defaultCacheImpl)
-      {
-         this.defaultCacheImpl = defaultCacheImpl;
-      }
-
-      public VFSCache run()
-      {
-         try
-         {
-            // First look to the input cache imple
-            String className = defaultCacheImpl;
-            if(className == null || className.length() == 0)
-            {
-               // Else look at the VFS_CACHE_KEY system property
-               className = System.getProperty(VFSUtils.VFS_CACHE_KEY);
-            }
-            if (className != null)
-            {
-               log.info("Initializing VFSCache [" + className + "] ...");
-               ClassLoader cl = VFSCacheFactory.class.getClassLoader();
-               Class<?> clazz = cl.loadClass(className);
-               VFSCache cache = VFSCache.class.cast(clazz.newInstance());
-               cache.start(); // start here, so we fall back to default no-op in case start fails
-               log.info("Using VFSCache [" + cache + "] ...");
-               return cache;
-            }
-         }
-         catch (Throwable t)
-         {
-            log.warn("Exception instantiating VFS cache: ", t);
-         }
-         log.info("Using VFSCache [NoopVFSCache] ...");
-         return new NoopVFSCache();
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java (from rev 80639, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/VFSCacheFactory.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,167 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.spi.cache;
+
+import java.lang.reflect.Constructor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.spi.cache.helpers.NoopVFSCache;
+
+/**
+ * Simple vfs cache factory.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 80615 $
+ */
+public class VFSCacheFactory
+{
+   private static final Object lock = new Object();
+   private static Logger log = Logger.getLogger(VFSCacheFactory.class);
+
+   private static VFSCache instance;
+
+   private VFSCacheFactory()
+   {
+   }
+
+   /**
+    * Get VFS cache instance.
+    *
+    * @return the vfs cache instance
+    */
+   public static VFSCache getInstance()
+   {
+      return getInstance(null, null);
+   }
+
+   /**
+    * 
+    * Get VFS cache instance.
+    *
+    * @param defaultCacheImpl - the possibly null name of the VFSCache
+    * implementation to use. If null, the {@linkplain VFSUtils.VFS_CACHE_KEY}
+    * system property will be used.
+    *
+    * @return the vfs cache instance
+    */
+   public static VFSCache getInstance(String defaultCacheImpl)
+   {
+      return getInstance(defaultCacheImpl, null);
+   }
+
+   /**
+    *
+    * Get VFS cache instance.
+    *
+    * @param defaultCacheImpl - the possibly null name of the VFSCache
+    * implementation to use. If null, the {@linkplain VFSUtils.VFS_CACHE_KEY}
+    * system property will be used.
+    * @param properties the possible vfs cache impl properties
+    *
+    * @return the vfs cache instance
+    */
+   public static VFSCache getInstance(String defaultCacheImpl, Map<Object, Object> properties)
+   {
+      if (instance == null)
+      {
+         synchronized (lock)
+         {
+            if (instance == null)
+               instance = AccessController.doPrivileged(new VFSCacheCreatorAction(defaultCacheImpl, properties));
+         }
+      }
+      return instance;
+   }
+
+   /**
+    * Set instance.
+    *
+    * This should be used with care.
+    * Better to leave it to getInstance method creation.
+    *
+    * @param cache cache instance to set
+    */
+   public static void setInstance(VFSCache cache)
+   {
+      if (cache != null && instance != null && instance instanceof NoopVFSCache == false)
+         throw new IllegalArgumentException("Instance already set!");
+
+      instance = cache;
+   }
+
+   private static class VFSCacheCreatorAction implements PrivilegedAction<VFSCache>
+   {
+      private String defaultCacheImpl;
+      private Map<Object, Object> properties;
+
+      VFSCacheCreatorAction(String defaultCacheImpl, Map<Object, Object> properties)
+      {
+         this.defaultCacheImpl = defaultCacheImpl;
+         this.properties = properties;
+      }
+
+      public VFSCache run()
+      {
+         try
+         {
+            // First look to the input cache imple
+            String className = defaultCacheImpl;
+            if(className == null || className.length() == 0)
+            {
+               // Else look at the VFS_CACHE_KEY system property
+               className = System.getProperty(VFSUtils.VFS_CACHE_KEY);
+            }
+            if (className != null)
+            {
+               log.info("Initializing VFSCache [" + className + "]");
+               ClassLoader cl = VFSCacheFactory.class.getClassLoader();
+               Class<?> clazz = cl.loadClass(className);
+               Object result;
+               if (properties != null)
+               {
+                  Constructor<?> constructor = clazz.getConstructor(Map.class);
+                  result = constructor.newInstance(properties);
+               }
+               else
+               {
+                  result = clazz.newInstance();
+               }
+               VFSCache cache = VFSCache.class.cast(result);
+               cache.start(); // start here, so we fall back to default no-op in case start fails
+               log.info("Using VFSCache [" + cache + "]");
+               return cache;
+            }
+         }
+         catch (Throwable t)
+         {
+            log.warn("Exception instantiating VFS cache: ", t);
+         }
+         log.info("Using VFSCache [NoopVFSCache]");
+         return new NoopVFSCache();
+      }
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,70 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.virtual.spi.cache.helpers;
-
-import java.net.URI;
-import java.net.URL;
-import java.io.IOException;
-
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.cache.VFSCache;
-
-/**
- * Noop cache.
- * Doesn't do any caching.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class NoopVFSCache implements VFSCache
-{
-   public VirtualFile getFile(URI uri) throws IOException
-   {
-      return VFS.getRoot(uri);
-   }
-
-   public VirtualFile getFile(URL url) throws IOException
-   {
-      return VFS.getRoot(url);
-   }
-
-   public void putContext(VFSContext context)
-   {
-   }
-
-   public void removeContext(VFSContext context)
-   {
-   }
-
-   public void start() throws Exception
-   {
-   }
-
-   public void stop()
-   {
-   }
-
-   public void flush()
-   {
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/main/java/org/jboss/virtual/spi/cache/helpers/NoopVFSCache.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,69 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.spi.cache.helpers;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.cache.VFSCache;
+
+/**
+ * Noop cache.
+ * Doesn't do any caching.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class NoopVFSCache implements VFSCache
+{
+   public VirtualFile getFile(URI uri) throws IOException
+   {
+      return null;
+   }
+
+   public VirtualFile getFile(URL url) throws IOException
+   {
+      return null;
+   }
+
+   public void putContext(VFSContext context)
+   {
+   }
+
+   public void removeContext(VFSContext context)
+   {
+   }
+
+   public void start() throws Exception
+   {
+   }
+
+   public void stop()
+   {
+   }
+
+   public void flush()
+   {
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,327 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.jboss.test.virtual.support.MockVirtualFileHandlerVisitor;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * AbstractVFSContextTest.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public abstract class AbstractVFSContextTest extends AbstractVFSTest
-{
-   public AbstractVFSContextTest(String name)
-   {
-      super(name);
-   }
-   
-   protected abstract VFSContext getVFSContext(String name) throws Exception;
-
-   protected abstract VFSContext getParentVFSContext() throws Exception;
-
-   protected abstract String getSuffix();
-
-   /* TODO URI testing
-   public void testRootURI() throws Exception
-   {
-   }
-   */
-   
-   public void testGetVFS() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      URI rootURI = context.getRootURI();
-      VFS vfs = context.getVFS();
-      VirtualFile rootFile = vfs.getRoot();
-
-      URI uri = new URI("vfs" + rootURI);
-      URI rfUri = rootFile.toURI();
-      assertEquals(uri.getPath(), rfUri.getPath());
-   }
-   
-   public void testGetRoot() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      URI rootURI = context.getRootURI();
-      VirtualFileHandler rootHandler = context.getRoot(); 
-      VFS vfs = context.getVFS();
-      VirtualFile rootFile = vfs.getRoot();
-      
-      assertEquals(rootURI, rootHandler.toURI());
-      assertEquals(rootHandler.getVirtualFile(), rootFile);
-   }
-   
-   /* TODO getOptions
-   public void testGetOptions() throws Exception
-   {
-   }
-   */
-   
-   public void testGetChildren() throws Exception
-   {
-      VFSContext context = getVFSContext("children");
-      VirtualFileHandler root = context.getRoot();
-      List<VirtualFileHandler> children = context.getChildren(root, false);
-      
-      Set<String> expected = new HashSet<String>();
-      expected.add("child1");
-      expected.add("child2");
-      expected.add("child3");
-
-      Set<String> actual = new HashSet<String>();
-      for (VirtualFileHandler child : children)
-      {
-         if (child.getName().startsWith("META-INF") == false && child.getName().equals(".svn") == false)
-            actual.add(child.getName());
-      }
-      
-      assertEquals(expected, actual);
-   }
-
-   public void testGetChildrenNullFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      try
-      {
-         context.getChildren(null, false);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testFindChildRoot() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = context.getChild(root, "");
-      assertEquals(root, found);
-   }
-
-   public void testFindChild() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = context.getChild(root, "child");
-      assertEquals("child", found.getPathName());
-   }
-
-   public void testFindChildSubFolder() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = context.getChild(root, "subfolder");
-      assertEquals("subfolder", found.getPathName());
-   }
-
-   public void testFindChildSubChild() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = context.getChild(root, "subfolder/subchild");
-      assertEquals("subfolder/subchild", found.getPathName());
-   }
-
-   public void testFindChildDoesNotExist() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      try
-      {
-         assertNull(context.getChild(root, "doesnotexist"));
-      }
-      catch (Throwable t)
-      {
-         checkThrowableTemp(IOException.class, t);
-      }
-   }
-
-   public void testFindChildNullFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      try
-      {
-         context.getChild(null, "");
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testFindChildNullPath() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      try
-      {
-         context.getChild(root, null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testSpecialTokensOnLeaf() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler leaf = root.getChild("child");
-      assertTrue(leaf.isLeaf());
-      assertNotNull(leaf.getChild(".."));
-      assertNotNull(leaf.getChild("."));
-      leaf = root.getChild("subfolder/subchild");
-      assertTrue(leaf.isLeaf());
-      assertNotNull(leaf.getChild(".."));
-      assertNotNull(leaf.getChild("."));
-   }
-
-   public void testSimpleReversePath() throws Exception
-   {
-      checkSpecialPath("simple" + getSuffix() + "/../complex" + getSuffix() + "/subfolder/subsubfolder/../subchild", "subchild");
-   }
-
-   public void testComplexReversePath() throws Exception
-   {
-      checkSpecialPath("complex" + getSuffix() + "/../simple" + getSuffix() + "/child", "child");
-   }
-
-   public void testDirectOverTheTop() throws Exception
-   {
-      checkOverTheTop("..");
-   }
-
-   public void testMiddleOverTheTop() throws Exception
-   {
-      checkOverTheTop("complex" + getSuffix() + "/subfolder/../../../complex" + getSuffix() + "/subfolder");
-   }
-
-   protected void checkOverTheTop(String path) throws Exception
-   {
-      try
-      {
-         checkSpecialPath(path, null);
-         fail("Should not be here.");
-      }
-      catch(Exception e)
-      {
-         checkThrowable(IOException.class, e);
-      }
-   }
-
-   public void testCurrentAtTheStart() throws Exception
-   {
-      checkSpecialPath("./simple" + getSuffix() + "/child", "child");
-      checkSpecialPath("./complex" + getSuffix() + "/subfolder/subchild", "subchild");
-   }
-
-   public void testCurrentInTheMiddle() throws Exception
-   {
-      checkSpecialPath("simple" + getSuffix() + "/./child", "child");
-      checkSpecialPath("complex" + getSuffix() + "/./subfolder/subchild", "subchild");
-   }
-
-   public void testConcurrentCurrent() throws Exception
-   {
-      checkSpecialPath("././simple" + getSuffix() + "/././child", "child");
-      checkSpecialPath("././complex" + getSuffix() + "/././subfolder/subchild", "subchild");
-   }
-
-   protected void checkSpecialPath(String path, String fileName) throws Exception
-   {
-      VFSContext context = getParentVFSContext();
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, path);
-      assertNotNull(child);
-      assertTrue(child.isLeaf());
-      assertEquals(fileName, child.getName());
-   }
-
-   public void testVisit() throws Exception
-   {
-      VFSContext context = getVFSContext("children");
-      VirtualFileHandler root = context.getRoot();
-      MockVirtualFileHandlerVisitor visitor = new MockVirtualFileHandlerVisitor();
-      context.visit(root, visitor);
-      
-      Set<String> expected = new HashSet<String>();
-      expected.add("child1");
-      expected.add("child2");
-      expected.add("child3");
-
-      Set<String> actual = new HashSet<String>();
-      for (VirtualFileHandler child : visitor.getVisited())
-      {
-         if (child.getName().startsWith("META-INF") == false && child.getName().equals(".svn") == false)
-            actual.add(child.getName());
-      }
-      
-      assertEquals(expected, actual);
-   }
-
-   public void testVisitNullHandler() throws Exception
-   {
-      VFSContext context = getVFSContext("children");
-      MockVirtualFileHandlerVisitor visitor = new MockVirtualFileHandlerVisitor();
-      try
-      {
-         context.visit(null, visitor);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testVisitNullVisitor() throws Exception
-   {
-      VFSContext context = getVFSContext("children");
-      VirtualFileHandler root = context.getRoot();
-      try
-      {
-         context.visit(root, null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,402 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.test.virtual.support.MockVirtualFileHandlerVisitor;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * AbstractVFSContextTest.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractVFSContextTest extends AbstractVFSTest
+{
+   public AbstractVFSContextTest(String name)
+   {
+      super(name);
+   }
+   
+   protected abstract VFSContext getVFSContext(String name) throws Exception;
+
+   protected abstract VFSContext getParentVFSContext() throws Exception;
+
+   protected abstract String getSuffix();
+
+   protected abstract String getRealProtocol();
+
+   protected abstract String getRealURLEnd();
+
+   protected abstract String transformExpectedEnd(String expecetedEnd);
+
+   protected abstract boolean isRealURLSupported();
+
+   /* TODO URI testing
+   public void testRootURI() throws Exception
+   {
+   }
+   */
+
+   public void testRealURL() throws Exception
+   {
+      try
+      {
+         assertRealURL("children", null, null);
+         assertRealURL("children", "child1", null);
+         assertRealURL("complex", null, null);
+         assertRealURL("complex", "subfolder", null);
+         assertRealURL("complex", "subfolder/subchild", null);
+         assertRealURL("complex", "subfolder/subsubfolder", null);
+         assertRealURL("complex", "subfolder/subsubfolder/subsubchild", null);
+         assertRealURL("nested", null, null);
+         assertRealURL("nested", "complex.jar", null);
+         assertRealURL("nested", "complex.jar/subfolder", "complex.jar");
+         assertRealURL("nested", "complex.jar/subfolder/subchild", "complex.jar");
+         assertRealURL("nested", "complex.jar/subfolder/subsubfolder", "complex.jar");
+         assertRealURL("nested", "complex.jar/subfolder/subsubfolder/subsubchild", "complex.jar");
+
+         assertTrue(isRealURLSupported());
+      }
+      catch (Throwable t)
+      {
+         assertFalse(t.getMessage(), isRealURLSupported());
+      }
+   }
+
+   @SuppressWarnings("deprecation")
+   public void assertRealURL(String name, String path, String expectedEnd) throws Exception
+   {
+      VFSContext context = getVFSContext(name);
+      VirtualFile root = context.getRoot().getVirtualFile();
+      VirtualFile file = root;
+      if (path != null && path.length() > 0)
+         file = root.findChild(path);
+
+      URL realURL = VFSUtils.getRealURL(file);
+      String realURLString = realURL.toExternalForm();
+
+      URL rootURL = root.toURL();
+      String rootURLString = rootURL.toExternalForm();
+      int p = rootURLString.indexOf(":/");
+      int l = rootURLString.length() - 1;
+      if (rootURLString.charAt(l - 1) == '!')
+         l--;
+      String middle = rootURLString.substring(p, l);
+      String end;
+      expectedEnd = transformExpectedEnd(expectedEnd);
+      if (expectedEnd == null)
+      {
+         end = (path != null) ? path : "";
+      }
+      else
+      {
+         end = expectedEnd;
+      }
+
+      String expectedRealURL = getRealProtocol() + middle + getRealURLEnd() + end;
+      if (expectedRealURL.endsWith("/") && realURLString.endsWith("/") == false)
+         realURLString += "/";
+      if (expectedRealURL.endsWith("/") == false && realURLString.endsWith("/"))
+         expectedRealURL += "/";
+
+      assertEquals("Different real URL:", expectedRealURL, realURLString);
+   }
+
+   public void testGetVFS() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      URI rootURI = context.getRootURI();
+      VFS vfs = context.getVFS();
+      VirtualFile rootFile = vfs.getRoot();
+
+      URI uri = new URI("vfs" + rootURI);
+      URI rfUri = rootFile.toURI();
+      assertEquals(uri.getPath(), rfUri.getPath());
+   }
+   
+   public void testGetRoot() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      URI rootURI = context.getRootURI();
+      VirtualFileHandler rootHandler = context.getRoot(); 
+      VFS vfs = context.getVFS();
+      VirtualFile rootFile = vfs.getRoot();
+      
+      assertEquals(rootURI, rootHandler.toURI());
+      assertEquals(rootHandler.getVirtualFile(), rootFile);
+   }
+   
+   /* TODO getOptions
+   public void testGetOptions() throws Exception
+   {
+   }
+   */
+   
+   public void testGetChildren() throws Exception
+   {
+      VFSContext context = getVFSContext("children");
+      VirtualFileHandler root = context.getRoot();
+      List<VirtualFileHandler> children = context.getChildren(root, false);
+      
+      Set<String> expected = new HashSet<String>();
+      expected.add("child1");
+      expected.add("child2");
+      expected.add("child3");
+
+      Set<String> actual = new HashSet<String>();
+      for (VirtualFileHandler child : children)
+      {
+         if (child.getName().startsWith("META-INF") == false && child.getName().equals(".svn") == false)
+            actual.add(child.getName());
+      }
+      
+      assertEquals(expected, actual);
+   }
+
+   public void testGetChildrenNullFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      try
+      {
+         context.getChildren(null, false);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testFindChildRoot() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = context.getChild(root, "");
+      assertEquals(root, found);
+   }
+
+   public void testFindChild() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = context.getChild(root, "child");
+      assertEquals("child", found.getPathName());
+   }
+
+   public void testFindChildSubFolder() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = context.getChild(root, "subfolder");
+      assertEquals("subfolder", found.getPathName());
+   }
+
+   public void testFindChildSubChild() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = context.getChild(root, "subfolder/subchild");
+      assertEquals("subfolder/subchild", found.getPathName());
+   }
+
+   public void testFindChildDoesNotExist() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      try
+      {
+         assertNull(context.getChild(root, "doesnotexist"));
+      }
+      catch (Throwable t)
+      {
+         checkThrowableTemp(IOException.class, t);
+      }
+   }
+
+   public void testFindChildNullFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      try
+      {
+         context.getChild(null, "");
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testFindChildNullPath() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      try
+      {
+         context.getChild(root, null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testSpecialTokensOnLeaf() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler leaf = root.getChild("child");
+      assertTrue(leaf.isLeaf());
+      assertNotNull(leaf.getChild(".."));
+      assertNotNull(leaf.getChild("."));
+      leaf = root.getChild("subfolder/subchild");
+      assertTrue(leaf.isLeaf());
+      assertNotNull(leaf.getChild(".."));
+      assertNotNull(leaf.getChild("."));
+   }
+
+   public void testSimpleReversePath() throws Exception
+   {
+      checkSpecialPath("simple" + getSuffix() + "/../complex" + getSuffix() + "/subfolder/subsubfolder/../subchild", "subchild");
+   }
+
+   public void testComplexReversePath() throws Exception
+   {
+      checkSpecialPath("complex" + getSuffix() + "/../simple" + getSuffix() + "/child", "child");
+   }
+
+   public void testDirectOverTheTop() throws Exception
+   {
+      checkOverTheTop("..");
+   }
+
+   public void testMiddleOverTheTop() throws Exception
+   {
+      checkOverTheTop("complex" + getSuffix() + "/subfolder/../../../complex" + getSuffix() + "/subfolder");
+   }
+
+   protected void checkOverTheTop(String path) throws Exception
+   {
+      try
+      {
+         checkSpecialPath(path, null);
+         fail("Should not be here.");
+      }
+      catch(Exception e)
+      {
+         checkThrowable(IOException.class, e);
+      }
+   }
+
+   public void testCurrentAtTheStart() throws Exception
+   {
+      checkSpecialPath("./simple" + getSuffix() + "/child", "child");
+      checkSpecialPath("./complex" + getSuffix() + "/subfolder/subchild", "subchild");
+   }
+
+   public void testCurrentInTheMiddle() throws Exception
+   {
+      checkSpecialPath("simple" + getSuffix() + "/./child", "child");
+      checkSpecialPath("complex" + getSuffix() + "/./subfolder/subchild", "subchild");
+   }
+
+   public void testConcurrentCurrent() throws Exception
+   {
+      checkSpecialPath("././simple" + getSuffix() + "/././child", "child");
+      checkSpecialPath("././complex" + getSuffix() + "/././subfolder/subchild", "subchild");
+   }
+
+   protected void checkSpecialPath(String path, String fileName) throws Exception
+   {
+      VFSContext context = getParentVFSContext();
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, path);
+      assertNotNull(child);
+      assertTrue(child.isLeaf());
+      assertEquals(fileName, child.getName());
+   }
+
+   public void testVisit() throws Exception
+   {
+      VFSContext context = getVFSContext("children");
+      VirtualFileHandler root = context.getRoot();
+      MockVirtualFileHandlerVisitor visitor = new MockVirtualFileHandlerVisitor();
+      context.visit(root, visitor);
+      
+      Set<String> expected = new HashSet<String>();
+      expected.add("child1");
+      expected.add("child2");
+      expected.add("child3");
+
+      Set<String> actual = new HashSet<String>();
+      for (VirtualFileHandler child : visitor.getVisited())
+      {
+         if (child.getName().startsWith("META-INF") == false && child.getName().equals(".svn") == false)
+            actual.add(child.getName());
+      }
+      
+      assertEquals(expected, actual);
+   }
+
+   public void testVisitNullHandler() throws Exception
+   {
+      VFSContext context = getVFSContext("children");
+      MockVirtualFileHandlerVisitor visitor = new MockVirtualFileHandlerVisitor();
+      try
+      {
+         context.visit(null, visitor);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testVisitNullVisitor() throws Exception
+   {
+      VFSContext context = getVFSContext("children");
+      VirtualFileHandler root = context.getRoot();
+      try
+      {
+         context.visit(root, null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ExceptionHandlerTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/ExceptionHandlerTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ExceptionHandlerTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ExceptionHandlerTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,60 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.net.URL;
+import java.util.List;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.helpers.NamesExceptionHandler;
+
+/**
+ * ExceptionHandlerTestCase.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class ExceptionHandlerTestCase extends AbstractVFSTest
+{
+   public static Test suite()
+   {
+      return suite(ExceptionHandlerTestCase.class);
+   }
+
+   public ExceptionHandlerTestCase(String name)
+   {
+      super(name, true);
+   }
+
+   public void testZipEntriesInit() throws Exception
+   {
+      URL url = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(url);
+      vfs.setExceptionHandler(new NamesExceptionHandler("_sqljdbc.jar"));
+      VirtualFile root = vfs.getRoot();
+      VirtualFile zipeinit = root.findChild("zipeinit.jar");
+      VirtualFile child = zipeinit.findChild("sqljdbc.jar");
+      List<VirtualFile> children = child.getChildren();
+      assertTrue(children.isEmpty());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,66 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.net.URL;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * FileVFSContextUnitTestCase.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class FileVFSContextUnitTestCase extends AbstractVFSContextTest
-{
-   public FileVFSContextUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(FileVFSContextUnitTestCase.class);
-   }
-
-   protected VFSContext getVFSContext(String name) throws Exception
-   {
-      URL url = getResource("/vfs/context/file/" + name + "/");
-      return new FileSystemContext(url);
-   }
-
-   protected VFSContext getParentVFSContext() throws Exception
-   {
-      URL url = getResource("/vfs/context/file/");
-      return new FileSystemContext(url);
-   }
-
-   protected String getSuffix()
-   {
-      return "";
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,86 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.net.URL;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * FileVFSContextUnitTestCase.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class FileVFSContextUnitTestCase extends AbstractVFSContextTest
+{
+   public FileVFSContextUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(FileVFSContextUnitTestCase.class);
+   }
+
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getResource("/vfs/context/file/" + name + "/");
+      return new FileSystemContext(url);
+   }
+
+   protected VFSContext getParentVFSContext() throws Exception
+   {
+      URL url = getResource("/vfs/context/file/");
+      return new FileSystemContext(url);
+   }
+
+   protected String getSuffix()
+   {
+      return "";
+   }
+
+   protected String getRealProtocol()
+   {
+      return "file";
+   }
+
+   protected String getRealURLEnd()
+   {
+      return "/";
+   }
+
+   protected String transformExpectedEnd(String expecetedEnd)
+   {
+      return null;
+   }
+
+   protected boolean isRealURLSupported()
+   {
+      return true;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,1699 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.test.virtual.test;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.zip.ZipInputStream;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.test.virtual.support.ClassPathIterator;
-import org.jboss.test.virtual.support.ClassPathIterator.ClassPathEntry;
-import org.jboss.test.virtual.support.MetaDataMatchFilter;
-import org.jboss.virtual.MemoryFileFactory;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.VisitorAttributes;
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.plugins.context.jar.NestedJarFromStream;
-import org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter;
-import org.jboss.virtual.spi.LinkInfo;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VFSContextFactory;
-import org.jboss.virtual.spi.VFSContextFactoryLocator;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * Tests of the VFS implementation
- * 
- * @author Scott.Stark at jboss.org
- * @author adrian at jboss.org
- * @version $Revision: 55523 $
- */
-public class FileVFSUnitTestCase extends AbstractVFSTest
-{
-   public FileVFSUnitTestCase(String name)
-   {
-      super(name);
-   }
-   
-   protected FileVFSUnitTestCase(String name, boolean forceCopy)
-   {
-      super(name, forceCopy);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(FileVFSUnitTestCase.class);
-   }
-
-   /**
-    * Test that a VFSContextFactory can be created from the testcase CodeSource url
-    * @throws Exception
-    */
-   public void testVFSContextFactory()
-      throws Exception
-   {
-      URL root = getClass().getProtectionDomain().getCodeSource().getLocation();
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(root);
-      assertTrue("VFSContextFactory(CodeSource.Location) != null", factory != null);
-   }
-
-   /**
-    * Test that one can go from a file uri to VirtualFile and obtain the
-    * same VirtualFile using VirtualFile vfsfile uri
-    * @throws Exception
-    */
-   public void testVFSFileURIFactory()
-      throws Exception
-   {
-      URL rootURL = getClass().getProtectionDomain().getCodeSource().getLocation();
-      VFS rootVFS0 = VFS.getVFS(rootURL.toURI());
-      VirtualFile root0 = rootVFS0.getRoot();
-      VFS rootVFS1 = VFS.getVFS(root0.toURI());
-      VirtualFile root1 = rootVFS1.getRoot();
-      assertEquals(root0, root1);
-   }
-
-   /**
-    * Test that NestedJarFromStream can provide access to nested jar content
-    * @throws Exception
-    */
-   public void testNestedJarFromStream()
-      throws Exception
-   {
-      URL outer = getResource("/vfs/test/outer.jar");
-      String path = outer.getPath();
-      File outerJar = new File(path);
-      assertTrue(outerJar.getAbsolutePath()+" exists", outerJar.exists());
-      JarFile jf = new JarFile(outerJar);
-
-      URL rootURL = outerJar.getParentFile().toURL();
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURL);
-      VFSContext context = factory.getVFS(rootURL);
-
-      JarEntry jar1 = jf.getJarEntry("jar1.jar");
-      URL jar1URL = new URL(outerJar.toURL(), "jar1.jar");
-      VFSContextFactory pf1 = VFSContextFactoryLocator.getFactory(jar1URL);
-      VFSContext parent1 = pf1.getVFS(jar1URL);
-
-      ZipInputStream jis1 = new ZipInputStream(jf.getInputStream(jar1));
-      NestedJarFromStream njfs = new NestedJarFromStream(context, parent1.getRoot(), jis1, jar1URL, jf, jar1, "jar1.jar");
-      VirtualFileHandler e1 = njfs.getChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      assertNotNull(e1);
-      log.info("org/jboss/test/vfs/support/CommonClass.class: "+e1);
-      VirtualFileHandler mfe1 = njfs.getChild("META-INF/MANIFEST.MF");
-      assertNotNull("jar1!/META-INF/MANIFEST.MF", mfe1);
-      InputStream mfIS = mfe1.openStream();
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String title1 = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar1", title1);
-      mfIS.close();
-      njfs.close();
-
-      JarEntry jar2 = jf.getJarEntry("jar2.jar");
-      URL jar2URL = new URL(outerJar.toURL(), "jar2.jar");
-      VFSContextFactory pf2 = VFSContextFactoryLocator.getFactory(jar2URL);
-      VFSContext parent2 = pf2.getVFS(jar2URL);
-
-      ZipInputStream jis2 = new ZipInputStream(jf.getInputStream(jar2));
-      NestedJarFromStream njfs2 = new NestedJarFromStream(context, parent2.getRoot(), jis2, jar2URL, jf, jar2, "jar2.jar");
-      VirtualFileHandler e2 = njfs2.getChild("org/jboss/test/vfs/support/jar2/ClassInJar2.class");
-      assertNotNull(e2);
-      log.info("org/jboss/test/vfs/support/CommonClass.class: "+e2);
-      VirtualFileHandler mfe2 = njfs2.getChild("META-INF/MANIFEST.MF");
-      assertNotNull("jar2!/META-INF/MANIFEST.MF", mfe2);
-      InputStream mf2IS = mfe2.openStream();
-      Manifest mf2 = new Manifest(mf2IS);
-      Attributes mainAttrs2 = mf2.getMainAttributes();
-      String title2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar2", title2);
-      mf2IS.close();
-      njfs2.close();
-   }
-
-   /**
-    * Test reading the contents of nested jar entries.
-    * @throws Exception
-    */
-   public void testInnerJarFile()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile outerjar = vfs.findChild("outer.jar");
-      assertTrue("outer.jar != null", outerjar != null);
-      VirtualFile jar1 = outerjar.findChild("jar1.jar");
-      assertTrue("outer.jar/jar1.jar != null", jar1 != null);
-      VirtualFile jar2 = outerjar.findChild("jar2.jar");
-      assertTrue("outer.jar/jar2.jar != null", jar2 != null);
-
-      VirtualFile jar1MF = jar1.findChild("META-INF/MANIFEST.MF");
-      assertNotNull("jar1!/META-INF/MANIFEST.MF", jar1MF);
-      InputStream mfIS = jar1MF.openStream();
-      Manifest mf1 = new Manifest(mfIS);
-      Attributes mainAttrs1 = mf1.getMainAttributes();
-      String title1 = mainAttrs1.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar1", title1);
-      jar1MF.close();
-
-      VirtualFile jar2MF = jar2.findChild("META-INF/MANIFEST.MF");
-      assertNotNull("jar2!/META-INF/MANIFEST.MF", jar2MF);
-      InputStream mfIS2 = jar2MF.openStream();
-      Manifest mf2 = new Manifest(mfIS2);
-      Attributes mainAttrs2 = mf2.getMainAttributes();
-      String title2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar2", title2);
-      jar2MF.close();
-   }
-
-   /**
-    * Basic tests of accessing resources in a jar
-    * @throws Exception
-    */
-   public void testFindResource()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile jar = vfs.findChild("outer.jar");
-      assertTrue("outer.jar != null", jar != null);
-
-      /*
-      ArrayList<String> searchCtx = new ArrayList<String>();
-      searchCtx.add("outer.jar");
-      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
-      */
-      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
-      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
-      InputStream mfIS = metaInf.openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      mfIS.close();
-   }
-
-   /**
-    * Basic tests of accessing resources in a jar
-    * @throws Exception
-    */
-   public void testFindResourceUsingURLStream()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile jar = vfs.findChild("outer.jar");
-      assertTrue("outer.jar != null", jar != null);
-
-      /*
-      ArrayList<String> searchCtx = new ArrayList<String>();
-      searchCtx.add("outer.jar");
-      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
-      */
-      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
-      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
-      InputStream mfIS = metaInf.toURL().openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      mfIS.close();
-
-      String urlString = metaInf.toURL().toString();
-      URL mfURL = new URL(urlString);
-      mfIS = mfURL.openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      mf = new Manifest(mfIS);
-      mainAttrs = mf.getMainAttributes();
-      version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      mfIS.close();
-   }
-
-   /**
-    * Basic tests of accessing resources in a jar that does not
-    * have parent directory entries.
-    * @throws Exception
-    */
-   public void testFindResourceInFilesOnlyJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile jar = vfs.findChild("jar1-filesonly.jar");
-      assertTrue("jar1-filesonly.jar != null", jar != null);
-
-      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
-      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
-      InputStream mfIS = metaInf.toURL().openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar1-filesonly", title);
-      mfIS.close();
-
-      String urlString = metaInf.toURL().toString();
-      URL mfURL = new URL(urlString);
-      mfIS = mfURL.openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      mf = new Manifest(mfIS);
-      mainAttrs = mf.getMainAttributes();
-      version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar1-filesonly", title);
-      mfIS.close();
-   }
-
-   /**
-    * Basic tests of accessing resources in a war that does not
-    * have parent directory entries.
-    * @throws Exception
-    */
-   public void testFindResourceInFilesOnlyWar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile war2 = vfs.findChild("WarDeployApp_web.war");
-      assertTrue("WarDeployApp_web.war != null", war2 != null);
-
-      VirtualFile classes2 = war2.findChild("WEB-INF/classes");
-      assertTrue("WEB-INF/classes != null", classes2 != null);
-      assertTrue("WEB-INF/classes is not a leaf", classes2.isLeaf()==false);
-      classes2 = war2.findChild("WEB-INF/classes");
-      assertTrue("WEB-INF/classes != null", classes2 != null);
-      assertTrue("WEB-INF/classes is not a leaf", classes2.isLeaf()==false);
-
-      VirtualFile HelloJavaBean = classes2.findChild("com/sun/ts/tests/webservices/deploy/warDeploy/HelloJavaBean.class");
-      assertTrue("HelloJavaBean.class != null", HelloJavaBean != null);
-      assertTrue("HelloJavaBean.class is a leaf", HelloJavaBean.isLeaf());
-
-      VirtualFile war = vfs.findChild("filesonly.war");
-      assertTrue("filesonly.war != null", war != null);
-
-      VirtualFile classes = war.findChild("WEB-INF/classes");
-      assertTrue("WEB-INF/classes != null", classes != null);
-      assertTrue("WEB-INF/classes is not a leaf", classes.isLeaf()==false);
-
-      VirtualFile jar1 = war.findChild("WEB-INF/lib/jar1.jar");
-      assertTrue("WEB-INF/lib/jar1.jar != null", jar1 != null);
-      assertTrue("WEB-INF/lib/jar1.jar is not a leaf", jar1.isLeaf()==false);
-      VirtualFile ClassInJar1 = jar1.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      assertTrue("ClassInJar1.class != null", ClassInJar1 != null);
-      assertTrue("ClassInJar1.class is a leaf", ClassInJar1.isLeaf());
-
-      VirtualFile metaInf = war.findChild("META-INF/MANIFEST.MF");
-      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
-      InputStream mfIS = metaInf.toURL().openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("filesonly-war", title);
-      mfIS.close();
-
-      war.findChild("WEB-INF/classes");
-      assertTrue("WEB-INF/classes != null", classes != null);
-      assertTrue("WEB-INF/classes is not a leaf", classes.isLeaf()==false);
-   }
-
-   /**
-    * Validate iterating over a vfs url from a files only war.
-    * 
-    * @throws Exception
-    */
-   public void testFindClassesInFilesOnlyWar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile war = vfs.findChild("filesonly.war");
-      assertTrue("filesonly.war != null", war != null);
-
-      VirtualFile classes = war.findChild("WEB-INF/classes");
-      assertTrue("WEB-INF/classes != null", classes != null);
-      HashSet<String> names = new HashSet<String>();
-      ClassPathIterator iter = new ClassPathIterator(classes.toURL());
-      ClassPathEntry entry = null;
-      while( (entry = iter.getNextEntry()) != null )
-      {
-         names.add(entry.name);
-      }
-      log.debug(names);
-      assertTrue("org/jboss/test/vfs/support/jar1", names.contains("org/jboss/test/vfs/support/jar1"));
-      assertTrue("ClassInJar1.class", names.contains("org/jboss/test/vfs/support/jar1/ClassInJar1.class"));
-      assertTrue("ClassInJar1$InnerClass.class", names.contains("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class"));
-   }
-
-   public void testFindResourceUnpackedJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile jar = vfs.findChild("unpacked-outer.jar");
-      assertTrue("unpacked-outer.jar != null", jar != null);
-
-      /**
-      ArrayList<String> searchCtx = new ArrayList<String>();
-      searchCtx.add("unpacked-outer.jar");
-      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
-      */
-      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
-      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
-      InputStream mfIS = metaInf.openStream();
-      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
-      assertEquals("1.0.0.GA", version);
-      mfIS.close();
-   }
-
-   /**
-    * Test simple file resolution without search contexts
-    * @throws Exception
-    */
-   public void testResolveFile()
-      throws Exception
-   {
-      log.info("+++ testResolveFile, cwd="+(new File(".").getCanonicalPath()));
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      // Check resolving the root file
-      VirtualFile root = vfs.findChild("");
-      assertEquals("root name", "test", root.getName());
-      assertEquals("root path", "", root.getPathName());
-      assertFalse("root isDirectory", root.isLeaf());
-
-      // Find the outer.jar
-      VirtualFile outerJar = vfs.findChild("outer.jar");
-      assertNotNull("outer.jar", outerJar);
-      assertEquals("outer.jar name", "outer.jar", outerJar.getName());
-      assertEquals("outer.jar path", "outer.jar", outerJar.getPathName());
-      
-      VirtualFile outerJarMF = vfs.findChild("outer.jar/META-INF/MANIFEST.MF");
-      assertNotNull("outer.jar/META-INF/MANIFEST.MF", outerJarMF);
-
-      // Test a non-canonical path
-      rootURL = getResource("/vfs/sundry/../test");
-      // Check resolving the root file
-      root = vfs.findChild("");
-      assertEquals("root name", "test", root.getName());
-      assertEquals("root path", "", root.getPathName());
-      assertFalse("root isDirectory", root.isLeaf());
-   }
-
-   /**
-    * Validate resolving a .class file given a set of search contexts in the
-    * vfs that make up a classpath.
-    * 
-    * @throws Exception
-    */
-   public void testResolveClassFileInClassPath()
-      throws Exception
-   {
-      log.info("+++ testResolveFile, cwd="+(new File(".").getCanonicalPath()));
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      
-      // Find ClassInJar1.class
-      VirtualFile vf = vfs.findChild("jar1.jar");
-      VirtualFile c1 = vf.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      assertNotNull("ClassInJar1.class VF", c1);
-      log.debug("Found ClassInJar1.class: "+c1);
-
-      // Find ClassInJar1$InnerClass.class
-      VirtualFile c1i = vf.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
-      assertNotNull("ClassInJar1$InnerClass.class VF", c1i);
-      log.debug("Found ClassInJar1$InnerClass.class: "+c1i);
-
-      // Find ClassInJar2.class
-      vf = vfs.findChild("jar2.jar");
-      VirtualFile c2 = vf.findChild("org/jboss/test/vfs/support/jar2/ClassInJar2.class");
-      assertNotNull("ClassInJar2.class VF", c2);
-      log.debug("Found ClassInJar2.class: "+c2);
-   }
-
-   public void testResolveFileInUnpackedJar()
-      throws Exception
-   {
-      log.info("+++ testResolveFileInUnpackedJar, cwd="+(new File(".").getCanonicalPath()));
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      // Check resolving the root file
-      VirtualFile root = vfs.findChild("");
-      assertEquals("root name", "test", root.getName());
-      assertEquals("root path", "", root.getPathName());
-      assertFalse("root isDirectory", root.isLeaf());
-
-      // Find the outer.jar
-      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
-      assertNotNull("unpacked-outer.jar", outerJar);
-      assertEquals("unpacked-outer.jar name", "unpacked-outer.jar", outerJar.getName());
-      assertEquals("unpacked-outer.jar path", "unpacked-outer.jar", outerJar.getPathName());
-      
-      VirtualFile outerJarMF = vfs.findChild("unpacked-outer.jar/META-INF/MANIFEST.MF");
-      assertNotNull("unpacked-outer.jar/META-INF/MANIFEST.MF", outerJarMF);
-
-      // Check resolving the root file
-      root = vfs.findChild("");
-      assertEquals("root name", "test", root.getName());
-      assertEquals("root path", "", root.getPathName());
-      assertFalse("root isDirectory", root.isLeaf());
-   }
-
-   public void testFileNotFoundInUnpackedJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      // Find the outer.jar
-      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
-      assertNotNull("unpacked-outer.jar", outerJar);
-      assertNull(outerJar.getChild("WEB-INF"));
-   }
-
-   public void testNestedNestedParent() throws Exception
-   {
-      // TODO
-   }
-
-   public void testCopyNestedStream() throws Exception
-   {
-      // TODO
-   }
-
-/*
-   public void testNoCopyNestedStream()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/seam/jboss-seam-booking.ear");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile clazz = vfs.getChild("lib/commons-beanutils.jar/org/apache/commons/beanutils/BeanComparator.class");
-      assertNotNull(clazz);
-      URL url = clazz.toURL();
-      InputStream is = url.openStream();
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      byte[] tmp = new byte[1024];
-      int read = 0;
-      while ( (read = is.read(tmp)) >= 0 )
-         baos.write(tmp, 0, read);
-      byte[] bytes = baos.toByteArray();
-      int size = bytes.length;
-      System.out.println("size = " + size);
-   }
-*/
-
-   /**
-    * Test file resolution with nested jars
-    * @throws Exception
-    */
-   public void testInnerJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
-      log.info("IsFile: "+inner.isLeaf());
-      log.info(inner.getLastModified());
-      List<VirtualFile> contents = inner.getChildren();
-      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
-      assertTrue("jar1.jar children.length("+contents.size()+") >= 2", contents.size() >= 2);
-      for(VirtualFile vf : contents)
-      {
-         log.info("  "+vf.getName());
-      }
-      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
-      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
-      InputStream mfIS = jar1MF.openStream();
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
-      mfIS.close();
-   }
-
-   public void testInnerJarUsingURLStream()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
-      log.info("IsFile: "+inner.isLeaf());
-      log.info(inner.getLastModified());
-      List<VirtualFile> contents = inner.getChildren();
-      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
-      assertTrue("jar1.jar children.length("+contents.size()+") >= 2", contents.size() >= 2);
-      for(VirtualFile vf : contents)
-      {
-         log.info("  "+vf.getName());
-      }
-      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
-      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
-      InputStream mfIS = jar1MF.toURL().openStream();
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
-      mfIS.close();
-   }
-
-   /**
-    * Test a scan of the outer.jar vfs to locate all .class files
-    * @throws Exception
-    */
-   public void testClassScan()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test/outer.jar");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      HashSet<String> expectedClasses = new HashSet<String>();
-      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
-      expectedClasses.add("jar1-filesonly.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      expectedClasses.add("jar1-filesonly.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
-      expectedClasses.add("jar2.jar/org/jboss/test/vfs/support/jar2/ClassInJar2.class");
-      expectedClasses.add("org/jboss/test/vfs/support/CommonClass.class");
-      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
-      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
-      List<VirtualFile> classes = vfs.getChildren(classVisitor);
-      int count = 0;
-      for (VirtualFile cf : classes)
-      {
-         String path = cf.getPathName();
-         if( path.endsWith(".class") )
-         {
-            assertTrue(path, expectedClasses.contains(path));
-            count ++;
-         }
-      }
-      assertEquals("There were 6 classes", 6, count);
-   }
-
-   /**
-    * Test a scan of the unpacked-outer.jar vfs to locate all .class files
-    * @throws Exception
-    */
-   public void testClassScanUnpacked()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test/unpacked-outer.jar");
-      VFS vfs = VFS.getVFS(rootURL);
-   
-      HashSet<String> expectedClasses = new HashSet<String>();
-      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
-      expectedClasses.add("jar2.jar/org/jboss/test/vfs/support/jar2/ClassInJar2.class");
-      // FIXME: .class files are not being copied from the resources directory
-      expectedClasses.add("org/jboss/test/vfs/support/CommonClass.class");
-      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
-      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
-      List<VirtualFile> classes = vfs.getChildren(classVisitor);
-      int count = 0;
-      for (VirtualFile cf : classes)
-      {
-         String path = cf.getPathName();
-         if( path.endsWith(".class") )
-         {
-            assertTrue(path, expectedClasses.contains(path));
-            count ++;
-         }
-      }
-      assertEquals("There were 4 classes", 4, count);
-   }
-
-   /**
-    * Test a scan of the jar1-filesonly.jar vfs to locate all .class files
-    * @throws Exception
-    */
-   public void testClassScanFilesonly()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test/jar1-filesonly.jar");
-      VFS vfs = VFS.getVFS(rootURL);
-   
-      HashSet<String> expectedClasses = new HashSet<String>();
-      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
-      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
-      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
-      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
-      List<VirtualFile> classes = vfs.getChildren(classVisitor);
-      int count = 0;
-      for (VirtualFile cf : classes)
-      {
-         String path = cf.getPathName();
-         if( path.endsWith(".class") )
-         {
-            assertTrue(path, expectedClasses.contains(path));
-            count ++;
-         }
-      }
-      assertEquals("There were 2 classes", 2, count);
-
-      // Make sure we can walk path-wise to the class
-      VirtualFile parent = vfs.getRoot();
-      String className = "org/jboss/test/vfs/support/jar1/ClassInJar1.class";
-      VirtualFile classInJar1 = vfs.findChild(className);
-      String[] paths = className.split("/");
-      StringBuilder vfsPath = new StringBuilder();
-      for(String path : paths)
-      {
-         vfsPath.append(path);
-         VirtualFile vf = parent.findChild(path);
-         if( path.equals("ClassInJar1.class") )
-            assertEquals("ClassInJar1.class", classInJar1, vf);
-         else
-         {
-            assertEquals("vfsPath", vfsPath.toString(), vf.getPathName());
-            // why should this be equal?
-            // assertEquals("lastModified", classInJar1.getLastModified(), vf.getLastModified());
-            assertTrue("lastModified", classInJar1.getLastModified() <= vf.getLastModified());
-         }
-         vfsPath.append('/');
-         parent = vf;
-      }
-   }
-
-   /**
-    * Test access of directories in a jar that only stores files
-    * @throws Exception
-    */
-   public void testFilesOnlyJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile jar = vfs.findChild("jar1-filesonly.jar");
-      VirtualFile metadataLocation = jar.findChild("META-INF");
-      assertNotNull(metadataLocation);
-      VirtualFile mfFile = metadataLocation.findChild("MANIFEST.MF");
-      assertNotNull(mfFile);
-      InputStream is = mfFile.openStream();
-      Manifest mf = new Manifest(is);
-      mfFile.close();
-      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
-
-      // Retry starting from the jar root
-      mfFile = jar.findChild("META-INF/MANIFEST.MF");
-      is = mfFile.openStream();
-      mf = new Manifest(is);
-      mfFile.close();
-      title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
-   }
-
-   /**
-    * Test the serialization of VirtualFiles
-    * @throws Exception
-    */
-   public void testVFSerialization()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      tmpRoot.deleteOnExit();
-      File tmp = new File(tmpRoot, "vfs.ser");
-      tmp.createNewFile();
-      tmp.deleteOnExit();
-      log.info("+++ testVFSerialization, tmp="+tmp.getCanonicalPath());
-      URL rootURL = tmpRoot.toURL();
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tmpVF = vfs.findChild("vfs.ser");
-      FileOutputStream fos = new FileOutputStream(tmp);
-      ObjectOutputStream oos = new ObjectOutputStream(fos);
-      oos.writeObject(tmpVF);
-      oos.close();
-
-      // Check the tmpVF attributes against the tmp file
-      long lastModified = tmp.lastModified();
-      long size = tmp.length();
-      String name = tmp.getName();
-      String vfsPath = tmp.getPath();
-      vfsPath = vfsPath.substring(tmpRoot.getPath().length()+1);
-      URL url = new URL("vfs" + tmp.toURL());
-      log.debug("name: "+name);
-      log.debug("vfsPath: "+vfsPath);
-      log.debug("url: "+url);
-      log.debug("lastModified: "+lastModified);
-      log.debug("size: "+size);
-      assertEquals("name", name, tmpVF.getName());
-      assertEquals("pathName", vfsPath, tmpVF.getPathName());
-      assertEquals("lastModified", lastModified, tmpVF.getLastModified());
-      assertEquals("size", size, tmpVF.getSize());
-      assertEquals("url", url, tmpVF.toURL());
-      assertEquals("isLeaf", true, tmpVF.isLeaf());
-      assertEquals("isHidden", false, tmpVF.isHidden());
-
-      // Read in the VF from the serialized file
-      FileInputStream fis = new FileInputStream(tmp);
-      ObjectInputStream ois = new ObjectInputStream(fis);
-      VirtualFile tmpVF2 = (VirtualFile) ois.readObject();
-      ois.close();
-      // Validated the deserialized attribtes against the tmp file
-      assertEquals("name", name, tmpVF2.getName());
-      assertEquals("pathName", vfsPath, tmpVF2.getPathName());
-      assertEquals("lastModified", lastModified, tmpVF2.getLastModified());
-      assertEquals("size", size, tmpVF2.getSize());
-      assertEquals("url", url, tmpVF2.toURL());
-      assertEquals("isLeaf", true, tmpVF2.isLeaf());
-      assertEquals("isHidden", false, tmpVF2.isHidden());
-   }
-
-   /**
-    * Test the serialization of VirtualFiles representing a jar
-    * @throws Exception
-    */
-   public void testVFJarSerialization()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      tmpRoot.deleteOnExit();
-      // Create a test jar containing a txt file
-      File tmpJar = new File(tmpRoot, "tst.jar");
-      tmpJar.createNewFile();
-      tmpJar.deleteOnExit();
-      FileOutputStream fos = new FileOutputStream(tmpJar);
-      JarOutputStream jos = new JarOutputStream(fos);
-      // Write a text file to include in a test jar
-      JarEntry txtEntry = new JarEntry("tst.txt");
-      jos.putNextEntry(txtEntry);
-      txtEntry.setSize("testVFJarSerialization".length());
-      txtEntry.setTime(System.currentTimeMillis());
-      jos.write("testVFJarSerialization".getBytes());
-      jos.close();
-      log.info("+++ testVFJarSerialization, tmp="+tmpJar.getCanonicalPath());
-
-      URI rootURI = tmpRoot.toURI();
-      VFS vfs = VFS.getVFS(rootURI);
-      File vfsSer = new File(tmpRoot, "vfs.ser");
-      vfsSer.createNewFile();
-      vfsSer.deleteOnExit();
-
-      VirtualFile tmpVF = vfs.findChild("tst.jar");
-      // Validate the vf jar against the tmp file attributes
-      long lastModified = tmpJar.lastModified();
-      long size = tmpJar.length();
-      String name = tmpJar.getName();
-      String vfsPath = tmpJar.getPath();
-      vfsPath = vfsPath.substring(tmpRoot.getPath().length()+1);
-      URL url = new URL("vfs" + tmpJar.toURL());
-      //url = JarUtils.createJarURL(url);
-      log.debug("name: "+name);
-      log.debug("vfsPath: "+vfsPath);
-      log.debug("url: "+url);
-      log.debug("lastModified: "+lastModified);
-      log.debug("size: "+size);
-      assertEquals("name", name, tmpVF.getName());
-      assertEquals("pathName", vfsPath, tmpVF.getPathName());
-      assertEquals("lastModified", lastModified, tmpVF.getLastModified());
-      assertEquals("size", size, tmpVF.getSize());
-      assertEquals("url", url.getPath(), tmpVF.toURL().getPath());
-      // TODO: these should pass
-      //assertEquals("isFile", true, tmpVF.isFile());
-      //assertEquals("isDirectory", false, tmpVF.isDirectory());
-      assertEquals("isHidden", false, tmpVF.isHidden());
-      // Write out the vfs jar file
-      fos = new FileOutputStream(vfsSer);
-      ObjectOutputStream oos = new ObjectOutputStream(fos);
-      oos.writeObject(tmpVF);
-      oos.close();
-
-      // Read in the VF from the serialized file
-      FileInputStream fis = new FileInputStream(vfsSer);
-      ObjectInputStream ois = new ObjectInputStream(fis);
-      VirtualFile tmpVF2 = (VirtualFile) ois.readObject();
-      ois.close();
-      // Validate the vf jar against the tmp file attributes
-      assertEquals("name", name, tmpVF2.getName());
-      assertEquals("pathName", vfsPath, tmpVF2.getPathName());
-      assertEquals("lastModified", lastModified, tmpVF2.getLastModified());
-      assertEquals("size", size, tmpVF2.getSize());
-      assertEquals("url", url.getPath(), tmpVF2.toURL().getPath());
-      // TODO: these should pass
-      //assertEquals("isFile", true, tmpVF2.isFile());
-      //assertEquals("isDirectory", false, tmpVF2.isDirectory());
-      assertEquals("isHidden", false, tmpVF2.isHidden());
-   }
-
-   /**
-    * Test the serialization of VirtualFiles representing a jar
-    * @throws Exception
-    */
-   public void testVFNestedJarSerialization()
-      throws Exception
-   {
-      // this expects to be run with a working dir of the container root
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
-
-      File vfsSer = File.createTempFile("testVFNestedJarSerialization", ".ser");
-      vfsSer.deleteOnExit();
-      // Write out the vfs inner jar file
-      FileOutputStream fos = new FileOutputStream(vfsSer);
-      ObjectOutputStream oos = new ObjectOutputStream(fos);
-      oos.writeObject(inner);
-      oos.close();
-      
-      // Read in the VF from the serialized file
-      FileInputStream fis = new FileInputStream(vfsSer);
-      ObjectInputStream ois = new ObjectInputStream(fis);
-      inner = (VirtualFile) ois.readObject();
-      ois.close();
-      List<VirtualFile> contents = inner.getChildren();
-      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
-      // TODO - fix this once no_copy serialization is working
-      int size = isForceCopyEnabled(inner) ? 2 : 0;
-      assertTrue("jar1.jar children.length("+contents.size()+") is not " + size, contents.size() >= size);
-      for(VirtualFile vf : contents)
-      {
-         log.info("  "+vf.getName());
-      }
-      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
-/*
-      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
-      InputStream mfIS = jar1MF.openStream();
-      Manifest mf = new Manifest(mfIS);
-      Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
-      mfIS.close();
-*/
-   }
-
-   /**
-    * Test parsing of a vfs link properties file. It contains test.classes.url
-    * and test.lib.url system property references that are configured to
-    * point to the CodeSource location of this class and /vfs/sundry/jar/
-    * respectively.
-    * 
-    * @throws Exception
-    */
-   public void testVfsLinkProperties()
-      throws Exception
-   {
-      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
-      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
-      // Find resources to use as the WEB-INF/{classes,lib} link targets
-      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
-      assertNotNull("classesURL", classesURL);
-      System.setProperty("test.classes.url", classesURL.toString());
-      URL libURL = super.getResource("/vfs/sundry/jar");
-      assertNotNull("libURL", libURL);      
-      System.setProperty("test.lib.url", libURL.toString());
-
-      assertTrue("isLink", VFSUtils.isLink(linkURL.getPath()));
-      Properties props = new Properties();
-      InputStream linkIS = linkURL.openStream();
-      List<LinkInfo> infos = VFSUtils.readLinkInfo(linkIS, linkURL.getPath(), props);
-      assertEquals("LinkInfo count", 2, infos.size());
-      LinkInfo classesInfo = null;
-      LinkInfo libInfo = null;
-      for(LinkInfo info :infos)
-      {
-         if( info.getName().equals("WEB-INF/classes") )
-            classesInfo = info;
-         else if(info.getName().equals("WEB-INF/lib") )
-            libInfo = info;
-      }
-      assertNotNull("classesInfo", classesInfo);
-      assertEquals("classesInfo.target", classesURL.toURI(), classesInfo.getLinkTarget());
-      assertNotNull("libInfo", libInfo);
-      assertEquals("libInfo.target", libURL.toURI(), libInfo.getLinkTarget());
-   }
-
-   /**
-    * Test the test-link.war link
-    * @throws Exception
-    */
-   public void testWarLink()
-      throws Exception
-   {
-      // Find resources to use as the WEB-INF/{classes,lib} link targets
-      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
-      assertNotNull("classesURL", classesURL);
-      System.setProperty("test.classes.url", classesURL.toString());
-      URL libURL = super.getResource("/vfs/sundry/jar");
-      assertNotNull("libURL", libURL);      
-      System.setProperty("test.lib.url", libURL.toString());
-
-      // Root the vfs at the link file parent directory
-      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
-      File linkFile = new File(linkURL.toURI());
-      File vfsRoot = linkFile.getParentFile();
-      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
-      VFS vfs = VFS.getVFS(vfsRoot.toURI());
-
-      // We should find the test-link.war the link represents
-      VirtualFile war = vfs.findChild("test-link.war");
-      assertNotNull("war", war);
-
-      // Validate the WEB-INF/classes child link
-      VirtualFile classes = war.findChild("WEB-INF/classes");
-      String classesName = classes.getName();
-      String classesPathName = classes.getPathName();
-      boolean classesIsDirectory = classes.isLeaf() == false;
-      assertEquals("classes.name", "classes", classesName);
-      assertEquals("classes.pathName", "test-link.war/WEB-INF/classes", classesPathName);
-      assertEquals("classes.isDirectory", true, classesIsDirectory);
-      // Should be able to find this class since classes points to out codesource
-      VirtualFile thisClass = classes.findChild("org/jboss/test/virtual/test/FileVFSUnitTestCase.class");
-      assertEquals("FileVFSUnitTestCase.class", thisClass.getName());
-
-      // Validate the WEB-INF/lib child link
-      VirtualFile lib = war.findChild("WEB-INF/lib");
-      String libName = lib.getName();
-      String libPathName = lib.getPathName();
-      boolean libIsDirectory = lib.isLeaf() == false;
-      assertEquals("lib.name", "lib", libName);
-      assertEquals("lib.pathName", "test-link.war/WEB-INF/lib", libPathName);
-      assertEquals("lib.isDirectory", true, libIsDirectory);
-      // Should be able to find archive.jar under lib
-      VirtualFile archiveJar = lib.findChild("archive.jar");
-      assertEquals("archive.jar", archiveJar.getName());
-   }
-
-   /**
-    * Test configuration change detection on test-link.war link
-    * @throws Exception
-    */
-   public void testWarLinkUpdate()
-      throws Exception
-   {
-      // Setup the system properties used in test-link.war.vfslink.properties 
-      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
-      assertNotNull("classesURL", classesURL);
-      System.setProperty("test.classes.url", classesURL.toString());
-      URL libURL = super.getResource("/vfs/sundry/jar");
-      assertNotNull("libURL", libURL);
-      System.setProperty("test.lib.url", libURL.toString());
-
-      // Root the vfs at the link file parent directory
-      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
-      File linkFile = new File(linkURL.toURI());
-      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
-
-      // Setup VFS root in a temp directory
-      File root = File.createTempFile("jboss-vfs-testWarLinkUpdate", ".tmp");
-      root.delete();
-      root.mkdir();
-      log.info("Using root: "+root);
-
-      // There should be no test-link.war under the new tmp root
-      VFS vfs = VFS.getVFS(root.toURI());
-      VirtualFile link = vfs.getChild("test-link.war");
-      assertNull("test-link.war", link);
-
-      // Add the link properties, now test-link.war should exist
-      File propsFile = new File(root, "test-link.war.vfslink.properties");
-      VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
-      link = vfs.getChild("test-link.war");
-      assertNotNull("test-link.war", link);
-
-      List<VirtualFile> children = link.getChildren();
-      assertEquals("test-link.war has 1 child", 1, children.size());
-      assertEquals("WEB-INF has 2 children", 2, children.get(0).getChildren().size());
-
-      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
-      Thread.sleep(1005);
-
-      // modify properties file - add more children
-      URL dynamicClassRoot = new URL("vfsmemory", ".vfslink-test", "");
-      MemoryFileFactory.createRoot(dynamicClassRoot);
-
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      PrintWriter webOut = new PrintWriter(new OutputStreamWriter(baos, "UTF-8"));
-      webOut.println("<?xml version=\"1.0\" ?>");
-      webOut.println("<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n" +
-         "         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
-         "         xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\"\n" +
-         "         version=\"2.5\">");
-      webOut.println("</web-app>");
-      webOut.close();
-
-      MemoryFileFactory.putFile(dynamicClassRoot, baos.toByteArray());
-
-      PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(propsFile, true)));
-      out.println("vfs.link.name.2=WEB-INF/web.xml");
-      out.println("vfs.link.target.2=" + dynamicClassRoot.toExternalForm());
-      out.close();
-
-      Properties linkProps = new Properties();
-      InputStream propsIn = new FileInputStream(propsFile);
-      linkProps.load(propsIn);
-      assertEquals(1+3*2, linkProps.size());
-      assertEquals("vfs.link.name.0", "WEB-INF/classes", linkProps.getProperty("vfs.link.name.0"));
-      assertEquals("vfs.link.name.1", "WEB-INF/lib", linkProps.getProperty("vfs.link.name.1"));
-      assertEquals("vfs.link.name.2", "WEB-INF/web.xml", linkProps.getProperty("vfs.link.name.2"));
-      assertEquals("vfs.link.target.2", dynamicClassRoot.toExternalForm(), linkProps.getProperty("vfs.link.target.2"));
-      propsIn.close();
-
-      // You need to get a new reference to LinkHandler - to get up-to-date configuration
-      children = link.getChildren();
-      assertEquals("test-link.war has 1 child", 1, children.size());
-      log.info("WEB-INF children after update: "+children.get(0).getChildren());
-      assertEquals("WEB-INF has 3 children", 3, children.get(0).getChildren().size());
-
-      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
-      Thread.sleep(1005);
-      // modify properties file - remove all but first
-      BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(propsFile)));
-      baos = new ByteArrayOutputStream();
-      out = new PrintWriter(new OutputStreamWriter(baos));
-      String line = in.readLine();
-      while(line != null)
-      {
-         if (line.indexOf(".0=") != -1)
-            out.println(line);
-         line = in.readLine();
-      }
-      out.close();
-      in.close();
-
-      FileOutputStream fos = new FileOutputStream(propsFile);
-      fos.write(baos.toByteArray());
-      fos.close();
-
-      children = link.getChildren();
-      assertEquals("test-link.war has 1 child", 1, children.size());
-      assertEquals("WEB-INF has 1 child", 1, children.get(0).getChildren().size());
-
-      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
-      Thread.sleep(1005);
-      // modify properties file - remove all
-      fos = new FileOutputStream(propsFile);
-      fos.write(' ');
-      fos.close();
-
-      assertNotNull(link.getName() + " not null", link);
-      assertTrue(link.getName() + " exists()", link.exists());
-
-      children = link.getChildren();
-      assertTrue("Wrong number of children", children.size() == 0);
-
-      // remove properties file
-      assertTrue(propsFile.getName() + " delete()", propsFile.delete());
-
-      assertFalse(link.getName() + " exists() == false", link.exists());
-      VirtualFile oldLink = link;
-      link = vfs.getChild("test-link.war");
-      assertNull(oldLink.getName() + " is null", link);
-
-      children = vfs.getChildren();
-      assertTrue("Wrong number of children", children.size() == 0);
-
-      // put back .vfslink.properties
-      VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
-
-      assertTrue(oldLink.getName() + " exists()", oldLink.exists());
-      link = vfs.getChild("test-link.war");
-      assertNotNull("test-link.war", link);
-
-      children = link.getChildren();
-      assertTrue("Wrong number of children", children.size() == 1);
-      assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 2);
-   }
-
-  /**
-    * Test that the URL of a VFS corresponding to a directory ends in '/' so that
-    * URLs created relative to it are under the directory. This requires that
-    * build-test.xml artifacts exist.
-    * 
-    * @throws Exception
-    */
-   public void testDirURLs() throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
-      URL outerURL = outerJar.toURL();
-      log.debug("outerURL: "+outerURL);
-      assertTrue(outerURL+" ends in '/'", outerURL.getPath().endsWith("/"));
-      // Validate that jar1 is under unpacked-outer.jar
-      URL jar1URL = new URL(outerURL, "jar1.jar");
-      log.debug("jar1URL: "+jar1URL+", path="+jar1URL.getPath());
-      assertTrue("jar1URL path ends in unpacked-outer.jar/jar1.jar!/",
-            jar1URL.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
-      VirtualFile jar1 = outerJar.findChild("jar1.jar");
-      assertEquals(jar1URL.getPath(), jar1.toURL().getPath());
-
-      VirtualFile packedJar = vfs.findChild("jar1.jar");
-      jar1URL = packedJar.findChild("org/jboss/test/vfs/support").toURL();
-      assertTrue("Jar directory entry URLs must end in /: " + jar1URL.toString(), jar1URL.toString().endsWith("/"));
-   }
-
-   /**
-    * Test that the URI of a VFS corresponding to a directory ends in '/' so that
-    * URIs created relative to it are under the directory. This requires that
-    * build-test.xml artifacts exist.
-    * 
-    * @throws Exception
-    */
-   public void testDirURIs() throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
-      URI outerURI = outerJar.toURI();
-      log.debug("outerURI: "+outerURI);
-      assertTrue(outerURI+" ends in '/'", outerURI.getPath().endsWith("/"));
-      // Validate that jar1 is under unpacked-outer.jar
-      URI jar1URI = new URI(outerURI+"jar1.jar");
-      log.debug("jar1URI: "+jar1URI+", path="+jar1URI.getPath());
-      assertTrue("jar1URI path ends in unpacked-outer.jar/jar1.jar!/",
-            jar1URI.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
-      VirtualFile jar1 = outerJar.findChild("jar1.jar");
-      assertEquals(jar1URI.getPath(), jar1.toURI().getPath());
-
-      VirtualFile packedJar = vfs.findChild("jar1.jar");
-      jar1URI = packedJar.findChild("org/jboss/test/vfs/support").toURI();
-      assertTrue("Jar directory entry URLs must end in /: " + jar1URI.toString(),
-            jar1URI.toString().endsWith("/"));
-   }
-
-   /**
-    * Test copying a jar
-    * 
-    * @throws Exception
-    */
-   public void testCopyJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile jar = vfs.findChild("outer.jar");
-      assertTrue("outer.jar != null", jar != null);
-      File tmpJar = File.createTempFile("testCopyJar", ".jar");
-      tmpJar.deleteOnExit();
-
-      try
-      {
-         InputStream is = jar.openStream();
-         FileOutputStream fos = new FileOutputStream(tmpJar);
-         byte[] buffer = new byte[1024];
-         int read;
-         while( (read = is.read(buffer)) > 0 )
-         {
-            fos.write(buffer, 0, read);
-         }
-         fos.close();
-         log.debug("outer.jar size is: "+jar.getSize());
-         log.debug(tmpJar.getAbsolutePath()+" size is: "+tmpJar.length());
-         assertTrue("outer.jar > 0", jar.getSize() > 0);
-         assertEquals("copy jar size", jar.getSize(), tmpJar.length());
-         jar.close();
-      }
-      finally
-      {
-         try
-         {
-            tmpJar.delete();
-         }
-         catch(Exception ignore)
-         {
-         }
-      }
-   }
-
-   /**
-    * Test copying a jar that is nested in another jar.
-    * 
-    * @throws Exception
-    */
-   public void testCopyInnerJar()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile outerjar = vfs.findChild("outer.jar");
-      assertTrue("outer.jar != null", outerjar != null);
-      VirtualFile jar = outerjar.findChild("jar1.jar");
-      assertTrue("outer.jar/jar1.jar != null", jar != null);
-
-      File tmpJar = File.createTempFile("testCopyInnerJar", ".jar");
-      tmpJar.deleteOnExit();
-
-      try
-      {
-         InputStream is = jar.openStream();
-         FileOutputStream fos = new FileOutputStream(tmpJar);
-         byte[] buffer = new byte[1024];
-         int read;
-         while( (read = is.read(buffer)) > 0 )
-         {
-            fos.write(buffer, 0, read);
-         }
-         fos.close();
-         log.debug("outer.jar/jar1.jar size is: "+jar.getSize());
-         log.debug(tmpJar.getAbsolutePath()+" size is: "+tmpJar.length());
-         assertTrue("outer.jar > 0", jar.getSize() > 0);
-         assertEquals("copy jar size", jar.getSize(), tmpJar.length());
-         jar.close();
-      }
-      finally
-      {
-         try
-         {
-            tmpJar.delete();
-         }
-         catch(Exception ignore)
-         {
-         }
-      }
-   }
-
-   /**
-    * Test that the outermf.jar manifest classpath is parsed
-    * correctly.
-    * 
-    * @throws Exception
-    */
-   public void testManifestClasspath()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile outerjar = vfs.findChild("outermf.jar");
-      assertNotNull("outermf.jar != null", outerjar);
-
-      ArrayList<VirtualFile> cp = new ArrayList<VirtualFile>();
-      VFSUtils.addManifestLocations(outerjar, cp);
-      // The p0.jar should be found in the classpath
-      assertEquals("cp size 2", 2, cp.size());
-      assertEquals("jar1.jar == cp[0]", "jar1.jar", cp.get(0).getName());
-      assertEquals("jar2.jar == cp[1]", "jar2.jar", cp.get(1).getName());
-   }
-   /**
-    * Test that an inner-inner jar that is extracted does not blowup
-    * the addManifestLocations routine.
-    * 
-    * @throws Exception
-    */
-   public void testInnerManifestClasspath()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile outerjar = vfs.getChild("withalong/rootprefix/outermf.jar");
-      assertNotNull(outerjar);
-      VirtualFile jar1 = outerjar.getChild("jar1.jar");
-      assertNotNull(jar1);
-      VirtualFile jar2 = outerjar.getChild("jar2.jar");
-      assertNotNull(jar2);
-      VirtualFile innerjar = outerjar.getChild("innermf.jar");
-      assertNotNull("innermf.jar != null", innerjar);
-   
-      ArrayList<VirtualFile> cp = new ArrayList<VirtualFile>();
-      VFSUtils.addManifestLocations(innerjar, cp);
-      assertEquals(2, cp.size());
-      VirtualFile cp0 = cp.get(0);
-      assertEquals(jar1, cp0);
-      VirtualFile cp1 = cp.get(1);
-      assertEquals(jar2, cp1);
-   }
-
-   /**
-    * Validate accessing an packed jar vf and its uri when the vfs path
-    * contains spaces
-    * @throws Exception
-    */
-   public void testJarWithSpacesInPath()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tstjar = vfs.findChild("path with spaces/tst.jar");
-      assertNotNull("tstjar != null", tstjar);
-      URI uri = tstjar.toURI();
-      URI expectedURI = new URI("vfs"+rootURL.toString()+"/path%20with%20spaces/tst.jar");
-      assertEquals(uri.getPath(), expectedURI.getPath());
-
-      InputStream is = uri.toURL().openStream();
-      is.close();
-
-      tstjar = vfs.findChild("path with spaces/tst%20nospace.jar");
-      assertNotNull("tstjar != null", tstjar);
-      uri = tstjar.toURI();
-      expectedURI = new URI("vfs"+rootURL.toString()+"/path%20with%20spaces/tst%2520nospace.jar");
-      assertEquals(uri.getPath(), expectedURI.getPath());
-
-      is = uri.toURL().openStream();
-      is.close();
-   }
-
-   public static void main(String[] args) throws Exception
-   {
-      File file = new File("C:\\Documents and Settings");
-      System.out.println(file.toURI());
-      System.out.println(file.toURL().getHost());
-      URI uri = new URI("file", null, "/Document and Settings", null);
-      System.out.println(uri);
-   }
-
-   /**
-    * Validate accessing an unpacked jar vf and its uri when the vfs path
-    * contains spaces
-    * @throws Exception
-    */
-   public void testUnpackedJarWithSpacesInPath()
-      throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tstjar = vfs.findChild("path with spaces/unpacked-tst.jar");
-      assertNotNull("tstjar != null", tstjar);
-      URI uri = tstjar.toURI();
-      URI expectedURI = new URI("vfs" + rootURL.toString()+"/path%20with%20spaces/unpacked-tst.jar/");
-      assertEquals(uri, expectedURI);
-   }
-
-   /**
-    * Tests that we can find the META-INF/some-data.xml in an unpacked deployment
-    * 
-    * @throws Exception for any error
-    */
-   public void testGetMetaDataUnpackedJar() throws Exception
-   {
-      testGetMetaDataFromJar("unpacked-with-metadata.jar");
-   }
-   
-   /**
-    * Tests that we can find the META-INF/some-data.xml in a packed deployment
-    * 
-    * @throws Exception for any error
-    */
-   public void testGetMetaDataPackedJar() throws Exception
-   {
-      testGetMetaDataFromJar("with-metadata.jar");
-   }
-   
-   private void testGetMetaDataFromJar(String name) throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      
-      VirtualFile jar = vfs.findChild(name);
-      assertNotNull(jar);
-      VirtualFile metadataLocation = jar.findChild("META-INF");
-      assertNotNull(metadataLocation);
-
-      VirtualFile metadataByName = metadataLocation.findChild("some-data.xml");
-      assertNotNull(metadataByName);
-      
-      //This is the same code as is called by AbstractDeploymentContext.getMetaDataFiles(String name, String suffix). 
-      //The MetaDataMatchFilter is a copy of the one used there
-      List<VirtualFile> metaDataList = metadataLocation.getChildren(new MetaDataMatchFilter(null, "-data.xml"));
-      assertNotNull(metaDataList);
-      assertEquals("Wrong size", 1, metaDataList.size());
-   }
-
-   /**
-    * Validate that a URLClassLoader.findReource/getResourceAsStream calls for non-existing absolute
-    * resources that should fail as expected with null results. Related to JBMICROCONT-139.
-    * 
-    * @throws Exception
-    */
-   public void testURLClassLoaderFindResourceFailure() throws Exception
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      URL[] cp = {vfs.getRoot().toURL()};
-      URLClassLoader ucl = new URLClassLoader(cp);
-      // Search for a non-existent resource
-      URL qp = ucl.findResource("nosuch-quartz.props");
-      assertNull("findResource(nosuch-quartz.props)", qp);
-      InputStream is = ucl.getResourceAsStream("nosuch-quartz.props");
-      assertNull("getResourceAsStream(nosuch-quartz.props)", is);
-   }
-
-   /**
-    * Test VirtualFile.exists for vfsfile based urls.
-    * 
-    * @throws Exception
-    */
-   public void testFileExists()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      File tmp = File.createTempFile("testFileExists", null, tmpRoot);
-      log.info("+++ testFileExists, tmp="+tmp.getCanonicalPath());
-
-      URL rootURL = tmpRoot.toURL();
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tmpVF = vfs.findChild(tmp.getName());
-      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue("tmp.delete()", tmpVF.delete());
-      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
-   }
-
-   /**
-    * Test VirtualFile.exists for vfsfile based urls for a directory.
-    * 
-    * @throws Exception
-    */
-   public void testDirFileExists()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      File tmp = File.createTempFile("testFileExists", null, tmpRoot);
-      assertTrue(tmp+".delete()", tmp.delete());
-      assertTrue(tmp+".mkdir()", tmp.mkdir());
-      log.info("+++ testDirFileExists, tmp="+tmp.getCanonicalPath());
-
-      URL rootURL = tmpRoot.toURL();
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tmpVF = vfs.findChild(tmp.getName());
-      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertFalse(tmpVF.getPathName()+".isLeaf()", tmpVF.isLeaf());
-      assertTrue(tmp+".delete()", tmp.delete());
-      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
-   }
-
-   /**
-    * Test VirtualFile.exists for vfsjar based urls.
-    * 
-    * @throws Exception
-    */
-   public void testJarExists()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      File tmpJar = File.createTempFile("testJarExists", ".jar", tmpRoot);
-      log.info("+++ testJarExists, tmpJar="+tmpJar.getCanonicalPath());
-      Manifest mf = new Manifest();
-      mf.getMainAttributes().putValue("Created-By", "FileVFSUnitTestCase.testJarExists");
-      FileOutputStream fos = new FileOutputStream(tmpJar);
-      JarOutputStream jos = new JarOutputStream(fos, mf);
-      jos.setComment("testJarExists");
-      jos.setLevel(0);
-      jos.close();
-
-      URL rootURL = tmpRoot.toURL();
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tmpVF = vfs.findChild(tmpJar.getName());
-      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue(tmpVF.getPathName()+".size() > 0", tmpVF.getSize() > 0);
-      assertTrue("tmp.delete()", tmpVF.delete());
-      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
-   }
-
-   /**
-    * Test VirtualFile.exists for vfsjar based urls for a directory.
-    * 
-    * @throws Exception
-    */
-   public void testDirJarExists()
-      throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      tmpRoot.delete();
-      tmpRoot.mkdir();
-      File tmp = File.createTempFile("testDirJarExists", ".jar", tmpRoot);
-      assertTrue(tmp+".delete()", tmp.delete());
-      assertTrue(tmp+".mkdir()", tmp.mkdir());
-      log.info("+++ testDirJarExists, tmp="+tmp.getCanonicalPath());
-
-      URL rootURL = tmpRoot.toURL();
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile tmpVF = vfs.findChild(tmp.getName());
-      log.info(tmpVF);
-      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertFalse(tmpVF.getPathName()+".isLeaf()", tmpVF.isLeaf());
-      assertTrue(tmp+".delete()", tmp.delete());
-      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
-      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
-   }
-
-   /**
-    * Test VirtualFile.delete() for file based urls
-    *
-    * @throws Exception
-    */
-   public void testFileDelete() throws Exception
-   {
-      File tmpRoot = File.createTempFile("vfs", ".root");
-      VFS vfs = VFS.getVFS(tmpRoot.toURL());
-
-      // non-existent directory - exists() not
-      tmpRoot.delete();
-      assertFalse(tmpRoot + ".exits() == false", vfs.getRoot().exists());
-
-      // existing directory - exists(), delete()
-      tmpRoot.mkdir();
-      assertTrue(tmpRoot + ".exits()", vfs.getRoot().exists());
-      assertTrue(tmpRoot + ".delete()", vfs.getRoot().delete());
-      tmpRoot.mkdir();
-
-      // non-empty directory - delete()
-      File tmp = new File(tmpRoot, "testFileDelete.jar");
-      assertTrue(tmp.mkdir());
-      File tmp2 = File.createTempFile("testFileDelete2", ".jar", tmp);
-      assertTrue(tmp2.exists());
-      VirtualFile tmpDeletable = VFS.getRoot(tmp.toURI());
-      assertTrue(tmpRoot + ".delete() == false", tmpDeletable.delete());
-
-      // create child to vfs
-      assertTrue(tmp.mkdir());
-      // children() exist
-      List<VirtualFile> children = vfs.getChildren();
-      assertTrue(tmpRoot + ".getChildren().size() == 1", children.size() == 1);
-
-      // specific child exists(), delete(), exists() not
-      VirtualFile tmpVF = vfs.getChild(tmp.getName());
-      assertTrue(tmp + ".exists()", tmpVF.exists());
-      assertTrue(tmp + ".delete()", tmpVF.delete());
-      assertFalse(tmp + ".exists() == false", tmpVF.exists());
-
-      // children() don't exist
-      children = vfs.getChildren();
-      assertTrue(tmpRoot + ".getChildren().size() == 0", children.size() == 0);
-
-      // getChild() returns null
-      tmpVF = vfs.getChild(tmp.getName());
-      assertNull(tmpRoot + ".getChild('" + tmp.getName() + "') == null", tmpVF);
-
-      // directory delete()
-      assertTrue(tmpRoot + ".delete()", vfs.getRoot().delete());
-   }
-
-   /**
-    * Test for <em>caseSensitive=true</em>
-    *
-    * If this test passes on unixes, it doesn't mean much, because there it should pass without
-    * case sensitivity turned on as well.
-    *
-    * If it passes on windows, it means the functionality works as expected.
-    *
-    * @throws Exception for any error
-    */
-   public void testCaseSensitive() throws Exception
-   {
-      URL rootURL = getResource("/vfs");
-
-      FileSystemContext ctx = new FileSystemContext(new URL(rootURL.toString() + "?caseSensitive=true"));
-      VirtualFileHandler root = ctx.getRoot();
-
-      String path = "context/file/simple/child";
-      VirtualFileHandler child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child != null);
-
-      path = "context/file/simple/CHILD";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child == null);
-
-      path = "context/jar/archive.jar";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child != null);
-
-      path = "context/JAR/archive.jar";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child == null);
-
-      path = "context/jar/archive.JAR";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child == null);
-
-      path = "context/jar/archive.jar/child";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child != null);
-
-      path = "context/jar/archive.jar/CHILD";
-      child = root.getChild(path);
-      assertTrue("getChild('" + path + "')", child == null);
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,1700 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.virtual.test;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipInputStream;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.test.virtual.support.ClassPathIterator;
+import org.jboss.test.virtual.support.ClassPathIterator.ClassPathEntry;
+import org.jboss.test.virtual.support.MetaDataMatchFilter;
+import org.jboss.virtual.MemoryFileFactory;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VisitorAttributes;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.jar.NestedJarFromStream;
+import org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter;
+import org.jboss.virtual.spi.LinkInfo;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VFSContextFactory;
+import org.jboss.virtual.spi.VFSContextFactoryLocator;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * Tests of the VFS implementation
+ * 
+ * @author Scott.Stark at jboss.org
+ * @author adrian at jboss.org
+ * @version $Revision: 55523 $
+ */
+public class FileVFSUnitTestCase extends AbstractVFSTest
+{
+   public FileVFSUnitTestCase(String name)
+   {
+      super(name);
+   }
+   
+   protected FileVFSUnitTestCase(String name, boolean forceCopy)
+   {
+      super(name, forceCopy);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(FileVFSUnitTestCase.class);
+   }
+
+   /**
+    * Test that a VFSContextFactory can be created from the testcase CodeSource url
+    * @throws Exception
+    */
+   public void testVFSContextFactory()
+      throws Exception
+   {
+      URL root = getClass().getProtectionDomain().getCodeSource().getLocation();
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(root);
+      assertTrue("VFSContextFactory(CodeSource.Location) != null", factory != null);
+   }
+
+   /**
+    * Test that one can go from a file uri to VirtualFile and obtain the
+    * same VirtualFile using VirtualFile vfsfile uri
+    * @throws Exception
+    */
+   public void testVFSFileURIFactory()
+      throws Exception
+   {
+      URL rootURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+      VFS rootVFS0 = VFS.getVFS(rootURL.toURI());
+      VirtualFile root0 = rootVFS0.getRoot();
+      VFS rootVFS1 = VFS.getVFS(root0.toURI());
+      VirtualFile root1 = rootVFS1.getRoot();
+      assertEquals(root0, root1);
+   }
+
+   /**
+    * Test that NestedJarFromStream can provide access to nested jar content
+    * @throws Exception
+    */
+   public void testNestedJarFromStream()
+      throws Exception
+   {
+      URL outer = getResource("/vfs/test/outer.jar");
+      String path = outer.getPath();
+      File outerJar = new File(path);
+      assertTrue(outerJar.getAbsolutePath()+" exists", outerJar.exists());
+      JarFile jf = new JarFile(outerJar);
+
+      URL rootURL = outerJar.getParentFile().toURL();
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURL);
+      VFSContext context = factory.getVFS(rootURL);
+
+      JarEntry jar1 = jf.getJarEntry("jar1.jar");
+      URL jar1URL = new URL(outerJar.toURL(), "jar1.jar");
+      VFSContextFactory pf1 = VFSContextFactoryLocator.getFactory(jar1URL);
+      VFSContext parent1 = pf1.getVFS(jar1URL);
+
+      ZipInputStream jis1 = new ZipInputStream(jf.getInputStream(jar1));
+      NestedJarFromStream njfs = new NestedJarFromStream(context, parent1.getRoot(), jis1, jar1URL, jf, jar1, "jar1.jar");
+      VirtualFileHandler e1 = njfs.getChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      assertNotNull(e1);
+      log.info("org/jboss/test/vfs/support/CommonClass.class: "+e1);
+      VirtualFileHandler mfe1 = njfs.getChild("META-INF/MANIFEST.MF");
+      assertNotNull("jar1!/META-INF/MANIFEST.MF", mfe1);
+      InputStream mfIS = mfe1.openStream();
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String title1 = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar1", title1);
+      mfIS.close();
+      njfs.close();
+
+      JarEntry jar2 = jf.getJarEntry("jar2.jar");
+      URL jar2URL = new URL(outerJar.toURL(), "jar2.jar");
+      VFSContextFactory pf2 = VFSContextFactoryLocator.getFactory(jar2URL);
+      VFSContext parent2 = pf2.getVFS(jar2URL);
+
+      ZipInputStream jis2 = new ZipInputStream(jf.getInputStream(jar2));
+      NestedJarFromStream njfs2 = new NestedJarFromStream(context, parent2.getRoot(), jis2, jar2URL, jf, jar2, "jar2.jar");
+      VirtualFileHandler e2 = njfs2.getChild("org/jboss/test/vfs/support/jar2/ClassInJar2.class");
+      assertNotNull(e2);
+      log.info("org/jboss/test/vfs/support/CommonClass.class: "+e2);
+      VirtualFileHandler mfe2 = njfs2.getChild("META-INF/MANIFEST.MF");
+      assertNotNull("jar2!/META-INF/MANIFEST.MF", mfe2);
+      InputStream mf2IS = mfe2.openStream();
+      Manifest mf2 = new Manifest(mf2IS);
+      Attributes mainAttrs2 = mf2.getMainAttributes();
+      String title2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar2", title2);
+      mf2IS.close();
+      njfs2.close();
+   }
+
+   /**
+    * Test reading the contents of nested jar entries.
+    * @throws Exception
+    */
+   public void testInnerJarFile()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile outerjar = vfs.findChild("outer.jar");
+      assertTrue("outer.jar != null", outerjar != null);
+      VirtualFile jar1 = outerjar.findChild("jar1.jar");
+      assertTrue("outer.jar/jar1.jar != null", jar1 != null);
+      VirtualFile jar2 = outerjar.findChild("jar2.jar");
+      assertTrue("outer.jar/jar2.jar != null", jar2 != null);
+
+      VirtualFile jar1MF = jar1.findChild("META-INF/MANIFEST.MF");
+      assertNotNull("jar1!/META-INF/MANIFEST.MF", jar1MF);
+      InputStream mfIS = jar1MF.openStream();
+      Manifest mf1 = new Manifest(mfIS);
+      Attributes mainAttrs1 = mf1.getMainAttributes();
+      String title1 = mainAttrs1.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar1", title1);
+      jar1MF.close();
+
+      VirtualFile jar2MF = jar2.findChild("META-INF/MANIFEST.MF");
+      assertNotNull("jar2!/META-INF/MANIFEST.MF", jar2MF);
+      InputStream mfIS2 = jar2MF.openStream();
+      Manifest mf2 = new Manifest(mfIS2);
+      Attributes mainAttrs2 = mf2.getMainAttributes();
+      String title2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar2", title2);
+      jar2MF.close();
+   }
+
+   /**
+    * Basic tests of accessing resources in a jar
+    * @throws Exception
+    */
+   public void testFindResource()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile jar = vfs.findChild("outer.jar");
+      assertTrue("outer.jar != null", jar != null);
+
+      /*
+      ArrayList<String> searchCtx = new ArrayList<String>();
+      searchCtx.add("outer.jar");
+      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
+      */
+      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
+      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
+      InputStream mfIS = metaInf.openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      mfIS.close();
+   }
+
+   /**
+    * Basic tests of accessing resources in a jar
+    * @throws Exception
+    */
+   public void testFindResourceUsingURLStream()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile jar = vfs.findChild("outer.jar");
+      assertTrue("outer.jar != null", jar != null);
+
+      /*
+      ArrayList<String> searchCtx = new ArrayList<String>();
+      searchCtx.add("outer.jar");
+      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
+      */
+      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
+      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
+      InputStream mfIS = metaInf.toURL().openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      mfIS.close();
+
+      String urlString = metaInf.toURL().toString();
+      URL mfURL = new URL(urlString);
+      mfIS = mfURL.openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      mf = new Manifest(mfIS);
+      mainAttrs = mf.getMainAttributes();
+      version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      mfIS.close();
+   }
+
+   /**
+    * Basic tests of accessing resources in a jar that does not
+    * have parent directory entries.
+    * @throws Exception
+    */
+   public void testFindResourceInFilesOnlyJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile jar = vfs.findChild("jar1-filesonly.jar");
+      assertTrue("jar1-filesonly.jar != null", jar != null);
+
+      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
+      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
+      InputStream mfIS = metaInf.toURL().openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar1-filesonly", title);
+      mfIS.close();
+
+      String urlString = metaInf.toURL().toString();
+      URL mfURL = new URL(urlString);
+      mfIS = mfURL.openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      mf = new Manifest(mfIS);
+      mainAttrs = mf.getMainAttributes();
+      version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar1-filesonly", title);
+      mfIS.close();
+   }
+
+   /**
+    * Basic tests of accessing resources in a war that does not
+    * have parent directory entries.
+    * @throws Exception
+    */
+   public void testFindResourceInFilesOnlyWar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile war2 = vfs.findChild("WarDeployApp_web.war");
+      assertTrue("WarDeployApp_web.war != null", war2 != null);
+
+      VirtualFile classes2 = war2.findChild("WEB-INF/classes");
+      assertTrue("WEB-INF/classes != null", classes2 != null);
+      assertTrue("WEB-INF/classes is not a leaf", classes2.isLeaf()==false);
+      classes2 = war2.findChild("WEB-INF/classes");
+      assertTrue("WEB-INF/classes != null", classes2 != null);
+      assertTrue("WEB-INF/classes is not a leaf", classes2.isLeaf()==false);
+
+      VirtualFile HelloJavaBean = classes2.findChild("com/sun/ts/tests/webservices/deploy/warDeploy/HelloJavaBean.class");
+      assertTrue("HelloJavaBean.class != null", HelloJavaBean != null);
+      assertTrue("HelloJavaBean.class is a leaf", HelloJavaBean.isLeaf());
+
+      VirtualFile war = vfs.findChild("filesonly.war");
+      assertTrue("filesonly.war != null", war != null);
+
+      VirtualFile classes = war.findChild("WEB-INF/classes");
+      assertTrue("WEB-INF/classes != null", classes != null);
+      assertTrue("WEB-INF/classes is not a leaf", classes.isLeaf()==false);
+
+      VirtualFile jar1 = war.findChild("WEB-INF/lib/jar1.jar");
+      assertTrue("WEB-INF/lib/jar1.jar != null", jar1 != null);
+      assertTrue("WEB-INF/lib/jar1.jar is not a leaf", jar1.isLeaf()==false);
+      VirtualFile ClassInJar1 = jar1.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      assertTrue("ClassInJar1.class != null", ClassInJar1 != null);
+      assertTrue("ClassInJar1.class is a leaf", ClassInJar1.isLeaf());
+
+      VirtualFile metaInf = war.findChild("META-INF/MANIFEST.MF");
+      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
+      InputStream mfIS = metaInf.toURL().openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("filesonly-war", title);
+      mfIS.close();
+
+      war.findChild("WEB-INF/classes");
+      assertTrue("WEB-INF/classes != null", classes != null);
+      assertTrue("WEB-INF/classes is not a leaf", classes.isLeaf()==false);
+   }
+
+   /**
+    * Validate iterating over a vfs url from a files only war.
+    * 
+    * @throws Exception
+    */
+   public void testFindClassesInFilesOnlyWar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile war = vfs.findChild("filesonly.war");
+      assertTrue("filesonly.war != null", war != null);
+
+      VirtualFile classes = war.findChild("WEB-INF/classes");
+      assertTrue("WEB-INF/classes != null", classes != null);
+      HashSet<String> names = new HashSet<String>();
+      ClassPathIterator iter = new ClassPathIterator(classes.toURL());
+      ClassPathEntry entry = null;
+      while( (entry = iter.getNextEntry()) != null )
+      {
+         names.add(entry.name);
+      }
+      log.debug(names);
+      assertTrue("org/jboss/test/vfs/support/jar1", names.contains("org/jboss/test/vfs/support/jar1"));
+      assertTrue("ClassInJar1.class", names.contains("org/jboss/test/vfs/support/jar1/ClassInJar1.class"));
+      assertTrue("ClassInJar1$InnerClass.class", names.contains("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class"));
+   }
+
+   public void testFindResourceUnpackedJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile jar = vfs.findChild("unpacked-outer.jar");
+      assertTrue("unpacked-outer.jar != null", jar != null);
+
+      /**
+      ArrayList<String> searchCtx = new ArrayList<String>();
+      searchCtx.add("unpacked-outer.jar");
+      VirtualFile metaInf = vfs.resolveFile("META-INF/MANIFEST.MF", searchCtx);
+      */
+      VirtualFile metaInf = jar.findChild("META-INF/MANIFEST.MF");
+      assertTrue("META-INF/MANIFEST.MF != null", metaInf != null);
+      InputStream mfIS = metaInf.openStream();
+      assertTrue("META-INF/MANIFEST.MF.openStream != null", mfIS != null);
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
+      assertEquals("1.0.0.GA", version);
+      mfIS.close();
+   }
+
+   /**
+    * Test simple file resolution without search contexts
+    * @throws Exception
+    */
+   public void testResolveFile()
+      throws Exception
+   {
+      log.info("+++ testResolveFile, cwd="+(new File(".").getCanonicalPath()));
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      // Check resolving the root file
+      VirtualFile root = vfs.findChild("");
+      assertEquals("root name", "test", root.getName());
+      assertEquals("root path", "", root.getPathName());
+      assertFalse("root isDirectory", root.isLeaf());
+
+      // Find the outer.jar
+      VirtualFile outerJar = vfs.findChild("outer.jar");
+      assertNotNull("outer.jar", outerJar);
+      assertEquals("outer.jar name", "outer.jar", outerJar.getName());
+      assertEquals("outer.jar path", "outer.jar", outerJar.getPathName());
+      
+      VirtualFile outerJarMF = vfs.findChild("outer.jar/META-INF/MANIFEST.MF");
+      assertNotNull("outer.jar/META-INF/MANIFEST.MF", outerJarMF);
+
+      // Test a non-canonical path
+      rootURL = getResource("/vfs/sundry/../test");
+      // Check resolving the root file
+      root = vfs.findChild("");
+      assertEquals("root name", "test", root.getName());
+      assertEquals("root path", "", root.getPathName());
+      assertFalse("root isDirectory", root.isLeaf());
+   }
+
+   /**
+    * Validate resolving a .class file given a set of search contexts in the
+    * vfs that make up a classpath.
+    * 
+    * @throws Exception
+    */
+   public void testResolveClassFileInClassPath()
+      throws Exception
+   {
+      log.info("+++ testResolveFile, cwd="+(new File(".").getCanonicalPath()));
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      
+      // Find ClassInJar1.class
+      VirtualFile vf = vfs.findChild("jar1.jar");
+      VirtualFile c1 = vf.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      assertNotNull("ClassInJar1.class VF", c1);
+      log.debug("Found ClassInJar1.class: "+c1);
+
+      // Find ClassInJar1$InnerClass.class
+      VirtualFile c1i = vf.findChild("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      assertNotNull("ClassInJar1$InnerClass.class VF", c1i);
+      log.debug("Found ClassInJar1$InnerClass.class: "+c1i);
+
+      // Find ClassInJar2.class
+      vf = vfs.findChild("jar2.jar");
+      VirtualFile c2 = vf.findChild("org/jboss/test/vfs/support/jar2/ClassInJar2.class");
+      assertNotNull("ClassInJar2.class VF", c2);
+      log.debug("Found ClassInJar2.class: "+c2);
+   }
+
+   public void testResolveFileInUnpackedJar()
+      throws Exception
+   {
+      log.info("+++ testResolveFileInUnpackedJar, cwd="+(new File(".").getCanonicalPath()));
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      // Check resolving the root file
+      VirtualFile root = vfs.findChild("");
+      assertEquals("root name", "test", root.getName());
+      assertEquals("root path", "", root.getPathName());
+      assertFalse("root isDirectory", root.isLeaf());
+
+      // Find the outer.jar
+      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
+      assertNotNull("unpacked-outer.jar", outerJar);
+      assertEquals("unpacked-outer.jar name", "unpacked-outer.jar", outerJar.getName());
+      assertEquals("unpacked-outer.jar path", "unpacked-outer.jar", outerJar.getPathName());
+      
+      VirtualFile outerJarMF = vfs.findChild("unpacked-outer.jar/META-INF/MANIFEST.MF");
+      assertNotNull("unpacked-outer.jar/META-INF/MANIFEST.MF", outerJarMF);
+
+      // Check resolving the root file
+      root = vfs.findChild("");
+      assertEquals("root name", "test", root.getName());
+      assertEquals("root path", "", root.getPathName());
+      assertFalse("root isDirectory", root.isLeaf());
+   }
+
+   public void testFileNotFoundInUnpackedJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      // Find the outer.jar
+      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
+      assertNotNull("unpacked-outer.jar", outerJar);
+      assertNull(outerJar.getChild("WEB-INF"));
+   }
+
+   public void testNestedNestedParent() throws Exception
+   {
+      // TODO
+   }
+
+   public void testCopyNestedStream() throws Exception
+   {
+      // TODO
+   }
+
+/*
+   public void testNoCopyNestedStream()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/seam/jboss-seam-booking.ear");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile clazz = vfs.getChild("lib/commons-beanutils.jar/org/apache/commons/beanutils/BeanComparator.class");
+      assertNotNull(clazz);
+      URL url = clazz.toURL();
+      InputStream is = url.openStream();
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      byte[] tmp = new byte[1024];
+      int read = 0;
+      while ( (read = is.read(tmp)) >= 0 )
+         baos.write(tmp, 0, read);
+      byte[] bytes = baos.toByteArray();
+      int size = bytes.length;
+      System.out.println("size = " + size);
+   }
+*/
+
+   /**
+    * Test file resolution with nested jars
+    * @throws Exception
+    */
+   public void testInnerJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
+      log.info("IsFile: "+inner.isLeaf());
+      log.info(inner.getLastModified());
+      List<VirtualFile> contents = inner.getChildren();
+      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
+      assertTrue("jar1.jar children.length("+contents.size()+") >= 2", contents.size() >= 2);
+      for(VirtualFile vf : contents)
+      {
+         log.info("  "+vf.getName());
+      }
+      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
+      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
+      InputStream mfIS = jar1MF.openStream();
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
+      mfIS.close();
+   }
+
+   public void testInnerJarUsingURLStream()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
+      log.info("IsFile: "+inner.isLeaf());
+      log.info(inner.getLastModified());
+      List<VirtualFile> contents = inner.getChildren();
+      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
+      assertTrue("jar1.jar children.length("+contents.size()+") >= 2", contents.size() >= 2);
+      for(VirtualFile vf : contents)
+      {
+         log.info("  "+vf.getName());
+      }
+      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
+      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
+      InputStream mfIS = jar1MF.toURL().openStream();
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
+      mfIS.close();
+   }
+
+   /**
+    * Test a scan of the outer.jar vfs to locate all .class files
+    * @throws Exception
+    */
+   public void testClassScan()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/outer.jar");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      HashSet<String> expectedClasses = new HashSet<String>();
+      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      expectedClasses.add("jar1-filesonly.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      expectedClasses.add("jar1-filesonly.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      expectedClasses.add("jar2.jar/org/jboss/test/vfs/support/jar2/ClassInJar2.class");
+      expectedClasses.add("org/jboss/test/vfs/support/CommonClass.class");
+      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
+      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
+      List<VirtualFile> classes = vfs.getChildren(classVisitor);
+      int count = 0;
+      for (VirtualFile cf : classes)
+      {
+         String path = cf.getPathName();
+         if( path.endsWith(".class") )
+         {
+            assertTrue(path, expectedClasses.contains(path));
+            count ++;
+         }
+      }
+      assertEquals("There were 6 classes", 6, count);
+   }
+
+   /**
+    * Test a scan of the unpacked-outer.jar vfs to locate all .class files
+    * @throws Exception
+    */
+   public void testClassScanUnpacked()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/unpacked-outer.jar");
+      VFS vfs = VFS.getVFS(rootURL);
+   
+      HashSet<String> expectedClasses = new HashSet<String>();
+      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      expectedClasses.add("jar1.jar/org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      expectedClasses.add("jar2.jar/org/jboss/test/vfs/support/jar2/ClassInJar2.class");
+      // FIXME: .class files are not being copied from the resources directory
+      expectedClasses.add("org/jboss/test/vfs/support/CommonClass.class");
+      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
+      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
+      List<VirtualFile> classes = vfs.getChildren(classVisitor);
+      int count = 0;
+      for (VirtualFile cf : classes)
+      {
+         String path = cf.getPathName();
+         if( path.endsWith(".class") )
+         {
+            assertTrue(path, expectedClasses.contains(path));
+            count ++;
+         }
+      }
+      assertEquals("There were 4 classes", 4, count);
+   }
+
+   /**
+    * Test a scan of the jar1-filesonly.jar vfs to locate all .class files
+    * @throws Exception
+    */
+   public void testClassScanFilesonly()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/jar1-filesonly.jar");
+      VFS vfs = VFS.getVFS(rootURL);
+   
+      HashSet<String> expectedClasses = new HashSet<String>();
+      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
+      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class", VisitorAttributes.RECURSE);
+      List<VirtualFile> classes = vfs.getChildren(classVisitor);
+      int count = 0;
+      for (VirtualFile cf : classes)
+      {
+         String path = cf.getPathName();
+         if( path.endsWith(".class") )
+         {
+            assertTrue(path, expectedClasses.contains(path));
+            count ++;
+         }
+      }
+      assertEquals("There were 2 classes", 2, count);
+
+      // Make sure we can walk path-wise to the class
+      VirtualFile parent = vfs.getRoot();
+      String className = "org/jboss/test/vfs/support/jar1/ClassInJar1.class";
+      VirtualFile classInJar1 = vfs.findChild(className);
+      String[] paths = className.split("/");
+      StringBuilder vfsPath = new StringBuilder();
+      for(String path : paths)
+      {
+         vfsPath.append(path);
+         VirtualFile vf = parent.findChild(path);
+         if( path.equals("ClassInJar1.class") )
+            assertEquals("ClassInJar1.class", classInJar1, vf);
+         else
+         {
+            assertEquals("vfsPath", vfsPath.toString(), vf.getPathName());
+            // why should this be equal?
+            // assertEquals("lastModified", classInJar1.getLastModified(), vf.getLastModified());
+            assertTrue("lastModified", classInJar1.getLastModified() <= vf.getLastModified());
+         }
+         vfsPath.append('/');
+         parent = vf;
+      }
+   }
+
+   /**
+    * Test access of directories in a jar that only stores files
+    * @throws Exception
+    */
+   public void testFilesOnlyJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile jar = vfs.findChild("jar1-filesonly.jar");
+      VirtualFile metadataLocation = jar.findChild("META-INF");
+      assertNotNull(metadataLocation);
+      VirtualFile mfFile = metadataLocation.findChild("MANIFEST.MF");
+      assertNotNull(mfFile);
+      InputStream is = mfFile.openStream();
+      Manifest mf = new Manifest(is);
+      mfFile.close();
+      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
+
+      // Retry starting from the jar root
+      mfFile = jar.findChild("META-INF/MANIFEST.MF");
+      is = mfFile.openStream();
+      mf = new Manifest(is);
+      mfFile.close();
+      title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
+   }
+
+   /**
+    * Test the serialization of VirtualFiles
+    * @throws Exception
+    */
+   public void testVFSerialization()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      tmpRoot.deleteOnExit();
+      File tmp = new File(tmpRoot, "vfs.ser");
+      tmp.createNewFile();
+      tmp.deleteOnExit();
+      log.info("+++ testVFSerialization, tmp="+tmp.getCanonicalPath());
+      URL rootURL = tmpRoot.toURL();
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tmpVF = vfs.findChild("vfs.ser");
+      FileOutputStream fos = new FileOutputStream(tmp);
+      ObjectOutputStream oos = new ObjectOutputStream(fos);
+      oos.writeObject(tmpVF);
+      oos.close();
+
+      // Check the tmpVF attributes against the tmp file
+      long lastModified = tmp.lastModified();
+      long size = tmp.length();
+      String name = tmp.getName();
+      String vfsPath = tmp.getPath();
+      vfsPath = vfsPath.substring(tmpRoot.getPath().length()+1);
+      URL url = new URL("vfs" + tmp.toURL());
+      log.debug("name: "+name);
+      log.debug("vfsPath: "+vfsPath);
+      log.debug("url: "+url);
+      log.debug("lastModified: "+lastModified);
+      log.debug("size: "+size);
+      assertEquals("name", name, tmpVF.getName());
+      assertEquals("pathName", vfsPath, tmpVF.getPathName());
+      assertEquals("lastModified", lastModified, tmpVF.getLastModified());
+      assertEquals("size", size, tmpVF.getSize());
+      assertEquals("url", url, tmpVF.toURL());
+      assertEquals("isLeaf", true, tmpVF.isLeaf());
+      assertEquals("isHidden", false, tmpVF.isHidden());
+
+      // Read in the VF from the serialized file
+      FileInputStream fis = new FileInputStream(tmp);
+      ObjectInputStream ois = new ObjectInputStream(fis);
+      VirtualFile tmpVF2 = (VirtualFile) ois.readObject();
+      ois.close();
+      // Validated the deserialized attribtes against the tmp file
+      assertEquals("name", name, tmpVF2.getName());
+      assertEquals("pathName", vfsPath, tmpVF2.getPathName());
+      assertEquals("lastModified", lastModified, tmpVF2.getLastModified());
+      assertEquals("size", size, tmpVF2.getSize());
+      assertEquals("url", url, tmpVF2.toURL());
+      assertEquals("isLeaf", true, tmpVF2.isLeaf());
+      assertEquals("isHidden", false, tmpVF2.isHidden());
+   }
+
+   /**
+    * Test the serialization of VirtualFiles representing a jar
+    * @throws Exception
+    */
+   public void testVFJarSerialization()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      tmpRoot.deleteOnExit();
+      // Create a test jar containing a txt file
+      File tmpJar = new File(tmpRoot, "tst.jar");
+      tmpJar.createNewFile();
+      tmpJar.deleteOnExit();
+      FileOutputStream fos = new FileOutputStream(tmpJar);
+      JarOutputStream jos = new JarOutputStream(fos);
+      // Write a text file to include in a test jar
+      JarEntry txtEntry = new JarEntry("tst.txt");
+      jos.putNextEntry(txtEntry);
+      txtEntry.setSize("testVFJarSerialization".length());
+      txtEntry.setTime(System.currentTimeMillis());
+      jos.write("testVFJarSerialization".getBytes());
+      jos.close();
+      log.info("+++ testVFJarSerialization, tmp="+tmpJar.getCanonicalPath());
+
+      URI rootURI = tmpRoot.toURI();
+      VFS vfs = VFS.getVFS(rootURI);
+      File vfsSer = new File(tmpRoot, "vfs.ser");
+      vfsSer.createNewFile();
+      vfsSer.deleteOnExit();
+
+      VirtualFile tmpVF = vfs.findChild("tst.jar");
+      // Validate the vf jar against the tmp file attributes
+      long lastModified = tmpJar.lastModified();
+      long size = tmpJar.length();
+      String name = tmpJar.getName();
+      String vfsPath = tmpJar.getPath();
+      vfsPath = vfsPath.substring(tmpRoot.getPath().length()+1);
+      URL url = new URL("vfs" + tmpJar.toURL());
+      //url = JarUtils.createJarURL(url);
+      log.debug("name: "+name);
+      log.debug("vfsPath: "+vfsPath);
+      log.debug("url: "+url);
+      log.debug("lastModified: "+lastModified);
+      log.debug("size: "+size);
+      assertEquals("name", name, tmpVF.getName());
+      assertEquals("pathName", vfsPath, tmpVF.getPathName());
+      assertEquals("lastModified", lastModified, tmpVF.getLastModified());
+      assertEquals("size", size, tmpVF.getSize());
+      assertEquals("url", url.getPath(), tmpVF.toURL().getPath());
+      // TODO: these should pass
+      //assertEquals("isFile", true, tmpVF.isFile());
+      //assertEquals("isDirectory", false, tmpVF.isDirectory());
+      assertEquals("isHidden", false, tmpVF.isHidden());
+      // Write out the vfs jar file
+      fos = new FileOutputStream(vfsSer);
+      ObjectOutputStream oos = new ObjectOutputStream(fos);
+      oos.writeObject(tmpVF);
+      oos.close();
+
+      // Read in the VF from the serialized file
+      FileInputStream fis = new FileInputStream(vfsSer);
+      ObjectInputStream ois = new ObjectInputStream(fis);
+      VirtualFile tmpVF2 = (VirtualFile) ois.readObject();
+      ois.close();
+      // Validate the vf jar against the tmp file attributes
+      assertEquals("name", name, tmpVF2.getName());
+      assertEquals("pathName", vfsPath, tmpVF2.getPathName());
+      assertEquals("lastModified", lastModified, tmpVF2.getLastModified());
+      assertEquals("size", size, tmpVF2.getSize());
+      assertEquals("url", url.getPath(), tmpVF2.toURL().getPath());
+      // TODO: these should pass
+      //assertEquals("isFile", true, tmpVF2.isFile());
+      //assertEquals("isDirectory", false, tmpVF2.isDirectory());
+      assertEquals("isHidden", false, tmpVF2.isHidden());
+   }
+
+   /**
+    * Test the serialization of VirtualFiles representing a jar
+    * @throws Exception
+    */
+   public void testVFNestedJarSerialization()
+      throws Exception
+   {
+      // this expects to be run with a working dir of the container root
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile inner = vfs.findChild("outer.jar/jar1.jar");
+
+      File vfsSer = File.createTempFile("testVFNestedJarSerialization", ".ser");
+      vfsSer.deleteOnExit();
+      // Write out the vfs inner jar file
+      FileOutputStream fos = new FileOutputStream(vfsSer);
+      ObjectOutputStream oos = new ObjectOutputStream(fos);
+      oos.writeObject(inner);
+      oos.close();
+      
+      // Read in the VF from the serialized file
+      FileInputStream fis = new FileInputStream(vfsSer);
+      ObjectInputStream ois = new ObjectInputStream(fis);
+      inner = (VirtualFile) ois.readObject();
+      ois.close();
+      List<VirtualFile> contents = inner.getChildren();
+      // META-INF/*, org/jboss/test/vfs/support/jar1/* at least
+      // TODO - fix this once no_copy serialization is working
+      int size = isForceCopyEnabled(inner) ? 2 : 0;
+      assertTrue("jar1.jar children.length("+contents.size()+") is not " + size, contents.size() >= size);
+      for(VirtualFile vf : contents)
+      {
+         log.info("  "+vf.getName());
+      }
+      VirtualFile vf = vfs.findChild("outer.jar/jar1.jar");
+/*
+      VirtualFile jar1MF = vf.findChild("META-INF/MANIFEST.MF");
+      InputStream mfIS = jar1MF.openStream();
+      Manifest mf = new Manifest(mfIS);
+      Attributes mainAttrs = mf.getMainAttributes();
+      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1", version);
+      mfIS.close();
+*/
+   }
+
+   /**
+    * Test parsing of a vfs link properties file. It contains test.classes.url
+    * and test.lib.url system property references that are configured to
+    * point to the CodeSource location of this class and /vfs/sundry/jar/
+    * respectively.
+    * 
+    * @throws Exception
+    */
+   public void testVfsLinkProperties()
+      throws Exception
+   {
+      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
+      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
+      // Find resources to use as the WEB-INF/{classes,lib} link targets
+      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+      assertNotNull("classesURL", classesURL);
+      System.setProperty("test.classes.url", classesURL.toString());
+      URL libURL = super.getResource("/vfs/sundry/jar");
+      assertNotNull("libURL", libURL);      
+      System.setProperty("test.lib.url", libURL.toString());
+
+      assertTrue("isLink", VFSUtils.isLink(linkURL.getPath()));
+      Properties props = new Properties();
+      InputStream linkIS = linkURL.openStream();
+      List<LinkInfo> infos = VFSUtils.readLinkInfo(linkIS, linkURL.getPath(), props);
+      assertEquals("LinkInfo count", 2, infos.size());
+      LinkInfo classesInfo = null;
+      LinkInfo libInfo = null;
+      for(LinkInfo info :infos)
+      {
+         if( info.getName().equals("WEB-INF/classes") )
+            classesInfo = info;
+         else if(info.getName().equals("WEB-INF/lib") )
+            libInfo = info;
+      }
+      assertNotNull("classesInfo", classesInfo);
+      assertEquals("classesInfo.target", classesURL.toURI(), classesInfo.getLinkTarget());
+      assertNotNull("libInfo", libInfo);
+      assertEquals("libInfo.target", libURL.toURI(), libInfo.getLinkTarget());
+   }
+
+   /**
+    * Test the test-link.war link
+    * @throws Exception
+    */
+   public void testWarLink()
+      throws Exception
+   {
+      // Find resources to use as the WEB-INF/{classes,lib} link targets
+      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+      assertNotNull("classesURL", classesURL);
+      System.setProperty("test.classes.url", classesURL.toString());
+      URL libURL = super.getResource("/vfs/sundry/jar");
+      assertNotNull("libURL", libURL);      
+      System.setProperty("test.lib.url", libURL.toString());
+
+      // Root the vfs at the link file parent directory
+      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
+      File linkFile = new File(linkURL.toURI());
+      File vfsRoot = linkFile.getParentFile();
+      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
+      VFS vfs = VFS.getVFS(vfsRoot.toURI());
+
+      // We should find the test-link.war the link represents
+      VirtualFile war = vfs.findChild("test-link.war");
+      assertNotNull("war", war);
+
+      // Validate the WEB-INF/classes child link
+      VirtualFile classes = war.findChild("WEB-INF/classes");
+      String classesName = classes.getName();
+      String classesPathName = classes.getPathName();
+      boolean classesIsDirectory = classes.isLeaf() == false;
+      assertEquals("classes.name", "classes", classesName);
+      assertEquals("classes.pathName", "test-link.war/WEB-INF/classes", classesPathName);
+      assertEquals("classes.isDirectory", true, classesIsDirectory);
+      // Should be able to find this class since classes points to out codesource
+      VirtualFile thisClass = classes.findChild("org/jboss/test/virtual/test/FileVFSUnitTestCase.class");
+      assertEquals("FileVFSUnitTestCase.class", thisClass.getName());
+
+      // Validate the WEB-INF/lib child link
+      VirtualFile lib = war.findChild("WEB-INF/lib");
+      String libName = lib.getName();
+      String libPathName = lib.getPathName();
+      boolean libIsDirectory = lib.isLeaf() == false;
+      assertEquals("lib.name", "lib", libName);
+      assertEquals("lib.pathName", "test-link.war/WEB-INF/lib", libPathName);
+      assertEquals("lib.isDirectory", true, libIsDirectory);
+      // Should be able to find archive.jar under lib
+      VirtualFile archiveJar = lib.findChild("archive.jar");
+      assertEquals("archive.jar", archiveJar.getName());
+   }
+
+   /**
+    * Test configuration change detection on test-link.war link
+    * @throws Exception
+    */
+   public void testWarLinkUpdate()
+      throws Exception
+   {
+      // Setup the system properties used in test-link.war.vfslink.properties 
+      URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+      assertNotNull("classesURL", classesURL);
+      System.setProperty("test.classes.url", classesURL.toString());
+      URL libURL = super.getResource("/vfs/sundry/jar");
+      assertNotNull("libURL", libURL);
+      System.setProperty("test.lib.url", libURL.toString());
+
+      // Root the vfs at the link file parent directory
+      URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
+      File linkFile = new File(linkURL.toURI());
+      assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
+
+      // Setup VFS root in a temp directory
+      File root = File.createTempFile("jboss-vfs-testWarLinkUpdate", ".tmp");
+      root.delete();
+      root.mkdir();
+      log.info("Using root: "+root);
+
+      // There should be no test-link.war under the new tmp root
+      VFS vfs = VFS.getVFS(root.toURI());
+      VirtualFile link = vfs.getChild("test-link.war");
+      assertNull("test-link.war", link);
+
+      // Add the link properties, now test-link.war should exist
+      File propsFile = new File(root, "test-link.war.vfslink.properties");
+      VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
+      link = vfs.getChild("test-link.war");
+      assertNotNull("test-link.war", link);
+
+      List<VirtualFile> children = link.getChildren();
+      assertEquals("test-link.war has 1 child", 1, children.size());
+      assertEquals("WEB-INF has 2 children", 2, children.get(0).getChildren().size());
+
+      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
+      Thread.sleep(1005);
+
+      // modify properties file - add more children
+      URL dynamicClassRoot = new URL("vfsmemory", ".vfslink-test", "");
+      MemoryFileFactory.createRoot(dynamicClassRoot);
+
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      PrintWriter webOut = new PrintWriter(new OutputStreamWriter(baos, "UTF-8"));
+      webOut.println("<?xml version=\"1.0\" ?>");
+      webOut.println("<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n" +
+         "         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+         "         xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\"\n" +
+         "         version=\"2.5\">");
+      webOut.println("</web-app>");
+      webOut.close();
+
+      MemoryFileFactory.putFile(dynamicClassRoot, baos.toByteArray());
+
+      PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(propsFile, true)));
+      out.println("vfs.link.name.2=WEB-INF/web.xml");
+      out.println("vfs.link.target.2=" + dynamicClassRoot.toExternalForm());
+      out.close();
+
+      Properties linkProps = new Properties();
+      InputStream propsIn = new FileInputStream(propsFile);
+      linkProps.load(propsIn);
+      assertEquals(1+3*2, linkProps.size());
+      assertEquals("vfs.link.name.0", "WEB-INF/classes", linkProps.getProperty("vfs.link.name.0"));
+      assertEquals("vfs.link.name.1", "WEB-INF/lib", linkProps.getProperty("vfs.link.name.1"));
+      assertEquals("vfs.link.name.2", "WEB-INF/web.xml", linkProps.getProperty("vfs.link.name.2"));
+      assertEquals("vfs.link.target.2", dynamicClassRoot.toExternalForm(), linkProps.getProperty("vfs.link.target.2"));
+      propsIn.close();
+
+      // You need to get a new reference to LinkHandler - to get up-to-date configuration
+      children = link.getChildren();
+      assertEquals("test-link.war has 1 child", 1, children.size());
+      log.info("WEB-INF children after update: "+children.get(0).getChildren());
+      assertEquals("WEB-INF has 3 children", 3, children.get(0).getChildren().size());
+
+      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
+      Thread.sleep(1005);
+      // modify properties file - remove all but first
+      BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(propsFile)));
+      baos = new ByteArrayOutputStream();
+      out = new PrintWriter(new OutputStreamWriter(baos));
+      String line = in.readLine();
+      while(line != null)
+      {
+         if (line.indexOf(".0=") != -1)
+            out.println(line);
+         line = in.readLine();
+      }
+      out.close();
+      in.close();
+
+      FileOutputStream fos = new FileOutputStream(propsFile);
+      fos.write(baos.toByteArray());
+      fos.close();
+
+      children = link.getChildren();
+      assertEquals("test-link.war has 1 child", 1, children.size());
+      assertEquals("WEB-INF has 1 child", 1, children.get(0).getChildren().size());
+
+      // Sleep 1sec+ to allow timestamp changes in files to be > 1000ms, JBVFS-59
+      Thread.sleep(1005);
+      // modify properties file - remove all
+      fos = new FileOutputStream(propsFile);
+      fos.write(' ');
+      fos.close();
+
+      assertNotNull(link.getName() + " not null", link);
+      assertTrue(link.getName() + " exists()", link.exists());
+
+      children = link.getChildren();
+      assertTrue("Wrong number of children", children.size() == 0);
+
+      // remove properties file
+      assertTrue(propsFile.getName() + " delete()", propsFile.delete());
+
+      assertFalse(link.getName() + " exists() == false", link.exists());
+      VirtualFile oldLink = link;
+      link = vfs.getChild("test-link.war");
+      assertNull(oldLink.getName() + " is null", link);
+
+      children = vfs.getChildren();
+      assertTrue("Wrong number of children", children.size() == 0);
+
+      // put back .vfslink.properties
+      VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
+
+      assertTrue(oldLink.getName() + " exists()", oldLink.exists());
+      link = vfs.getChild("test-link.war");
+      assertNotNull("test-link.war", link);
+
+      children = link.getChildren();
+      assertTrue("Wrong number of children", children.size() == 1);
+      assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 2);
+   }
+
+  /**
+    * Test that the URL of a VFS corresponding to a directory ends in '/' so that
+    * URLs created relative to it are under the directory. This requires that
+    * build-test.xml artifacts exist.
+    * 
+    * @throws Exception
+    */
+   public void testDirURLs() throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
+      URL outerURL = outerJar.toURL();
+      log.debug("outerURL: "+outerURL);
+      assertTrue(outerURL+" ends in '/'", outerURL.getPath().endsWith("/"));
+      // Validate that jar1 is under unpacked-outer.jar
+      URL jar1URL = new URL(outerURL, "jar1.jar");
+      log.debug("jar1URL: "+jar1URL+", path="+jar1URL.getPath());
+      assertTrue("jar1URL path ends in unpacked-outer.jar/jar1.jar!/",
+            jar1URL.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
+      VirtualFile jar1 = outerJar.findChild("jar1.jar");
+      assertEquals(jar1URL.getPath(), jar1.toURL().getPath());
+
+      VirtualFile packedJar = vfs.findChild("jar1.jar");
+      jar1URL = packedJar.findChild("org/jboss/test/vfs/support").toURL();
+      assertTrue("Jar directory entry URLs must end in /: " + jar1URL.toString(), jar1URL.toString().endsWith("/"));
+   }
+
+   /**
+    * Test that the URI of a VFS corresponding to a directory ends in '/' so that
+    * URIs created relative to it are under the directory. This requires that
+    * build-test.xml artifacts exist.
+    * 
+    * @throws Exception
+    */
+   public void testDirURIs() throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile outerJar = vfs.findChild("unpacked-outer.jar");
+      URI outerURI = outerJar.toURI();
+      log.debug("outerURI: "+outerURI);
+      assertTrue(outerURI+" ends in '/'", outerURI.getPath().endsWith("/"));
+      // Validate that jar1 is under unpacked-outer.jar
+      URI jar1URI = new URI(outerURI+"jar1.jar");
+      log.debug("jar1URI: "+jar1URI+", path="+jar1URI.getPath());
+      assertTrue("jar1URI path ends in unpacked-outer.jar/jar1.jar!/",
+            jar1URI.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
+      VirtualFile jar1 = outerJar.findChild("jar1.jar");
+      assertEquals(jar1URI.getPath(), jar1.toURI().getPath());
+
+      VirtualFile packedJar = vfs.findChild("jar1.jar");
+      jar1URI = packedJar.findChild("org/jboss/test/vfs/support").toURI();
+      assertTrue("Jar directory entry URLs must end in /: " + jar1URI.toString(),
+            jar1URI.toString().endsWith("/"));
+   }
+
+   /**
+    * Test copying a jar
+    * 
+    * @throws Exception
+    */
+   public void testCopyJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile jar = vfs.findChild("outer.jar");
+      assertTrue("outer.jar != null", jar != null);
+      File tmpJar = File.createTempFile("testCopyJar", ".jar");
+      tmpJar.deleteOnExit();
+
+      try
+      {
+         InputStream is = jar.openStream();
+         FileOutputStream fos = new FileOutputStream(tmpJar);
+         byte[] buffer = new byte[1024];
+         int read;
+         while( (read = is.read(buffer)) > 0 )
+         {
+            fos.write(buffer, 0, read);
+         }
+         fos.close();
+         log.debug("outer.jar size is: "+jar.getSize());
+         log.debug(tmpJar.getAbsolutePath()+" size is: "+tmpJar.length());
+         assertTrue("outer.jar > 0", jar.getSize() > 0);
+         assertEquals("copy jar size", jar.getSize(), tmpJar.length());
+         jar.close();
+      }
+      finally
+      {
+         try
+         {
+            tmpJar.delete();
+         }
+         catch(Exception ignore)
+         {
+         }
+      }
+   }
+
+   /**
+    * Test copying a jar that is nested in another jar.
+    * 
+    * @throws Exception
+    */
+   public void testCopyInnerJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile outerjar = vfs.findChild("outer.jar");
+      assertTrue("outer.jar != null", outerjar != null);
+      VirtualFile jar = outerjar.findChild("jar1.jar");
+      assertTrue("outer.jar/jar1.jar != null", jar != null);
+
+      File tmpJar = File.createTempFile("testCopyInnerJar", ".jar");
+      tmpJar.deleteOnExit();
+
+      try
+      {
+         InputStream is = jar.openStream();
+         FileOutputStream fos = new FileOutputStream(tmpJar);
+         byte[] buffer = new byte[1024];
+         int read;
+         while( (read = is.read(buffer)) > 0 )
+         {
+            fos.write(buffer, 0, read);
+         }
+         fos.close();
+         log.debug("outer.jar/jar1.jar size is: "+jar.getSize());
+         log.debug(tmpJar.getAbsolutePath()+" size is: "+tmpJar.length());
+         assertTrue("outer.jar > 0", jar.getSize() > 0);
+         assertEquals("copy jar size", jar.getSize(), tmpJar.length());
+         jar.close();
+      }
+      finally
+      {
+         try
+         {
+            tmpJar.delete();
+         }
+         catch(Exception ignore)
+         {
+         }
+      }
+   }
+
+   /**
+    * Test that the outermf.jar manifest classpath is parsed
+    * correctly.
+    * 
+    * @throws Exception
+    */
+   public void testManifestClasspath()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile outerjar = vfs.findChild("outermf.jar");
+      assertNotNull("outermf.jar != null", outerjar);
+
+      ArrayList<VirtualFile> cp = new ArrayList<VirtualFile>();
+      VFSUtils.addManifestLocations(outerjar, cp);
+      // The p0.jar should be found in the classpath
+      assertEquals("cp size 2", 2, cp.size());
+      assertEquals("jar1.jar == cp[0]", "jar1.jar", cp.get(0).getName());
+      assertEquals("jar2.jar == cp[1]", "jar2.jar", cp.get(1).getName());
+   }
+   /**
+    * Test that an inner-inner jar that is extracted does not blowup
+    * the addManifestLocations routine.
+    * 
+    * @throws Exception
+    */
+   public void testInnerManifestClasspath()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile outerjar = vfs.getChild("withalong/rootprefix/outermf.jar");
+      assertNotNull(outerjar);
+      VirtualFile jar1 = outerjar.getChild("jar1.jar");
+      assertNotNull(jar1);
+      VirtualFile jar2 = outerjar.getChild("jar2.jar");
+      assertNotNull(jar2);
+      VirtualFile innerjar = outerjar.getChild("innermf.jar");
+      assertNotNull("innermf.jar != null", innerjar);
+   
+      ArrayList<VirtualFile> cp = new ArrayList<VirtualFile>();
+      VFSUtils.addManifestLocations(innerjar, cp);
+      assertEquals(2, cp.size());
+      VirtualFile cp0 = cp.get(0);
+      assertEquals(jar1, cp0);
+      VirtualFile cp1 = cp.get(1);
+      assertEquals(jar2, cp1);
+   }
+
+   /**
+    * Validate accessing an packed jar vf and its uri when the vfs path
+    * contains spaces
+    * @throws Exception
+    */
+   public void testJarWithSpacesInPath()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tstjar = vfs.findChild("path with spaces/tst.jar");
+      assertNotNull("tstjar != null", tstjar);
+      URI uri = tstjar.toURI();
+      URI expectedURI = new URI("vfs"+rootURL.toString()+"/path%20with%20spaces/tst.jar");
+      assertEquals(uri.getPath(), expectedURI.getPath());
+
+      InputStream is = uri.toURL().openStream();
+      is.close();
+
+      tstjar = vfs.findChild("path with spaces/tst%20nospace.jar");
+      assertNotNull("tstjar != null", tstjar);
+      uri = tstjar.toURI();
+      expectedURI = new URI("vfs"+rootURL.toString()+"/path%20with%20spaces/tst%2520nospace.jar");
+      assertEquals(uri.getPath(), expectedURI.getPath());
+
+      is = uri.toURL().openStream();
+      is.close();
+   }
+
+   public static void main(String[] args) throws Exception
+   {
+      File file = new File("C:\\Documents and Settings");
+      System.out.println(file.toURI());
+      System.out.println(file.toURL().getHost());
+      URI uri = new URI("file", null, "/Document and Settings", null);
+      System.out.println(uri);
+   }
+
+   /**
+    * Validate accessing an unpacked jar vf and its uri when the vfs path
+    * contains spaces
+    * @throws Exception
+    */
+   public void testUnpackedJarWithSpacesInPath()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tstjar = vfs.findChild("path with spaces/unpacked-tst.jar");
+      assertNotNull("tstjar != null", tstjar);
+      URI uri = tstjar.toURI();
+      URI expectedURI = new URI("vfs" + rootURL.toString()+"/path%20with%20spaces/unpacked-tst.jar/");
+      assertEquals(uri, expectedURI);
+   }
+
+   /**
+    * Tests that we can find the META-INF/some-data.xml in an unpacked deployment
+    * 
+    * @throws Exception for any error
+    */
+   public void testGetMetaDataUnpackedJar() throws Exception
+   {
+      testGetMetaDataFromJar("unpacked-with-metadata.jar");
+   }
+   
+   /**
+    * Tests that we can find the META-INF/some-data.xml in a packed deployment
+    * 
+    * @throws Exception for any error
+    */
+   public void testGetMetaDataPackedJar() throws Exception
+   {
+      testGetMetaDataFromJar("with-metadata.jar");
+   }
+   
+   private void testGetMetaDataFromJar(String name) throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      
+      VirtualFile jar = vfs.findChild(name);
+      assertNotNull(jar);
+      VirtualFile metadataLocation = jar.findChild("META-INF");
+      assertNotNull(metadataLocation);
+
+      VirtualFile metadataByName = metadataLocation.findChild("some-data.xml");
+      assertNotNull(metadataByName);
+      
+      //This is the same code as is called by AbstractDeploymentContext.getMetaDataFiles(String name, String suffix). 
+      //The MetaDataMatchFilter is a copy of the one used there
+      List<VirtualFile> metaDataList = metadataLocation.getChildren(new MetaDataMatchFilter(null, "-data.xml"));
+      assertNotNull(metaDataList);
+      assertEquals("Wrong size", 1, metaDataList.size());
+   }
+
+   /**
+    * Validate that a URLClassLoader.findReource/getResourceAsStream calls for non-existing absolute
+    * resources that should fail as expected with null results. Related to JBMICROCONT-139.
+    * 
+    * @throws Exception
+    */
+   public void testURLClassLoaderFindResourceFailure() throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      URL[] cp = {vfs.getRoot().toURL()};
+      URLClassLoader ucl = new URLClassLoader(cp);
+      // Search for a non-existent resource
+      URL qp = ucl.findResource("nosuch-quartz.props");
+      assertNull("findResource(nosuch-quartz.props)", qp);
+      InputStream is = ucl.getResourceAsStream("nosuch-quartz.props");
+      assertNull("getResourceAsStream(nosuch-quartz.props)", is);
+   }
+
+   /**
+    * Test VirtualFile.exists for vfsfile based urls.
+    * 
+    * @throws Exception
+    */
+   public void testFileExists()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      File tmp = File.createTempFile("testFileExists", null, tmpRoot);
+      log.info("+++ testFileExists, tmp="+tmp.getCanonicalPath());
+
+      URL rootURL = tmpRoot.toURL();
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tmpVF = vfs.findChild(tmp.getName());
+      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue("tmp.delete()", tmpVF.delete());
+      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
+   }
+
+   /**
+    * Test VirtualFile.exists for vfsfile based urls for a directory.
+    * 
+    * @throws Exception
+    */
+   public void testDirFileExists()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      File tmp = File.createTempFile("testFileExists", null, tmpRoot);
+      assertTrue(tmp+".delete()", tmp.delete());
+      assertTrue(tmp+".mkdir()", tmp.mkdir());
+      log.info("+++ testDirFileExists, tmp="+tmp.getCanonicalPath());
+
+      URL rootURL = tmpRoot.toURL();
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tmpVF = vfs.findChild(tmp.getName());
+      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertFalse(tmpVF.getPathName()+".isLeaf()", tmpVF.isLeaf());
+      assertTrue(tmp+".delete()", tmp.delete());
+      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
+   }
+
+   /**
+    * Test VirtualFile.exists for vfsjar based urls.
+    * 
+    * @throws Exception
+    */
+   public void testJarExists()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      File tmpJar = File.createTempFile("testJarExists", ".jar", tmpRoot);
+      log.info("+++ testJarExists, tmpJar="+tmpJar.getCanonicalPath());
+      Manifest mf = new Manifest();
+      mf.getMainAttributes().putValue("Created-By", "FileVFSUnitTestCase.testJarExists");
+      FileOutputStream fos = new FileOutputStream(tmpJar);
+      JarOutputStream jos = new JarOutputStream(fos, mf);
+      jos.setComment("testJarExists");
+      jos.setLevel(0);
+      jos.close();
+
+      URL rootURL = tmpRoot.toURL();
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tmpVF = vfs.findChild(tmpJar.getName());
+      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue(tmpVF.getPathName()+".size() > 0", tmpVF.getSize() > 0);
+      assertTrue("tmp.delete()", tmpVF.delete());
+      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
+   }
+
+   /**
+    * Test VirtualFile.exists for vfsjar based urls for a directory.
+    * 
+    * @throws Exception
+    */
+   public void testDirJarExists()
+      throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      tmpRoot.delete();
+      tmpRoot.mkdir();
+      File tmp = File.createTempFile("testDirJarExists", ".jar", tmpRoot);
+      assertTrue(tmp+".delete()", tmp.delete());
+      assertTrue(tmp+".mkdir()", tmp.mkdir());
+      log.info("+++ testDirJarExists, tmp="+tmp.getCanonicalPath());
+
+      URL rootURL = tmpRoot.toURL();
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile tmpVF = vfs.findChild(tmp.getName());
+      log.info(tmpVF);
+      assertTrue(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertFalse(tmpVF.getPathName()+".isLeaf()", tmpVF.isLeaf());
+      assertTrue(tmp+".delete()", tmp.delete());
+      assertFalse(tmpVF.getPathName()+".exists()", tmpVF.exists());
+      assertTrue(tmpRoot+".delete()", tmpRoot.delete());
+   }
+
+   /**
+    * Test VirtualFile.delete() for file based urls
+    *
+    * @throws Exception
+    */
+   public void testFileDelete() throws Exception
+   {
+      File tmpRoot = File.createTempFile("vfs", ".root");
+      VFS vfs = VFS.getVFS(tmpRoot.toURL());
+      VirtualFile root = vfs.getRoot();
+
+      // non-existent directory - exists() not
+      tmpRoot.delete();
+      assertFalse(tmpRoot + ".exits() == false", root.exists());
+
+      // existing directory - exists(), delete()
+      tmpRoot.mkdir();
+      assertTrue(tmpRoot + ".exits()", root.exists());
+      assertTrue(tmpRoot + ".delete()", root.delete());
+      tmpRoot.mkdir();
+
+      // non-empty directory - delete()
+      File tmp = new File(tmpRoot, "testFileDelete.jar");
+      assertTrue(tmp.mkdir());
+      File tmp2 = File.createTempFile("testFileDelete2", ".jar", tmp);
+      assertTrue(tmp2.exists());
+      VirtualFile tmpDeletable = VFS.getRoot(tmp.toURI());
+      assertTrue(tmpRoot + ".delete() == false", tmpDeletable.delete());
+
+      // create child to vfs
+      assertTrue(tmp.mkdir());
+      // children() exist
+      List<VirtualFile> children = vfs.getChildren();
+      assertTrue(tmpRoot + ".getChildren().size() == 1", children.size() == 1);
+
+      // specific child exists(), delete(), exists() not
+      VirtualFile tmpVF = vfs.getChild(tmp.getName());
+      assertTrue(tmp + ".exists()", tmpVF.exists());
+      assertTrue(tmp + ".delete()", tmpVF.delete());
+      assertFalse(tmp + ".exists() == false", tmpVF.exists());
+
+      // children() don't exist
+      children = vfs.getChildren();
+      assertTrue(tmpRoot + ".getChildren().size() == 0", children.size() == 0);
+
+      // getChild() returns null
+      tmpVF = vfs.getChild(tmp.getName());
+      assertNull(tmpRoot + ".getChild('" + tmp.getName() + "') == null", tmpVF);
+
+      // directory delete()
+      assertTrue(tmpRoot + ".delete()", root.delete());
+   }
+
+   /**
+    * Test for <em>caseSensitive=true</em>
+    *
+    * If this test passes on unixes, it doesn't mean much, because there it should pass without
+    * case sensitivity turned on as well.
+    *
+    * If it passes on windows, it means the functionality works as expected.
+    *
+    * @throws Exception for any error
+    */
+   public void testCaseSensitive() throws Exception
+   {
+      URL rootURL = getResource("/vfs");
+
+      FileSystemContext ctx = new FileSystemContext(new URL(rootURL.toString() + "?caseSensitive=true"));
+      VirtualFileHandler root = ctx.getRoot();
+
+      String path = "context/file/simple/child";
+      VirtualFileHandler child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child != null);
+
+      path = "context/file/simple/CHILD";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child == null);
+
+      path = "context/jar/archive.jar";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child != null);
+
+      path = "context/JAR/archive.jar";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child == null);
+
+      path = "context/jar/archive.JAR";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child == null);
+
+      path = "context/jar/archive.jar/child";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child != null);
+
+      path = "context/jar/archive.jar/CHILD";
+      child = root.getChild(path);
+      assertTrue("getChild('" + path + "')", child == null);
+   }
+}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/IterableTimedCacheTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/IterableTimedCacheTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/IterableTimedCacheTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/IterableTimedCacheTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,49 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import junit.framework.Test;
+import org.jboss.virtual.plugins.cache.IterableTimedVFSCache;
+import org.jboss.virtual.spi.cache.VFSCache;
+
+/**
+ * Iterable timed VFSCache Test.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ */
+public class IterableTimedCacheTestCase extends TimedCacheTestCase
+{
+   public IterableTimedCacheTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(IterableTimedCacheTestCase.class);
+   }
+
+   protected VFSCache createCache()
+   {
+      return new IterableTimedVFSCache(5);
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,327 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.plugins.context.jar.JarContext;
-import org.jboss.virtual.plugins.context.jar.JarUtils;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * JARVFSContextUnitTestCase.
- *
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @version $Revision: 1.1 $
- */
-public class JARVFSContextUnitTestCase extends AbstractVFSContextTest
-{
-   public JARVFSContextUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      VFS.init();
-      System.out.println("java.protocol.handler.pkgs: " + System.getProperty("java.protocol.handler.pkgs"));
-      return new TestSuite(JARVFSContextUnitTestCase.class);
-   }
-
-   protected VFSContext getVFSContext(String name) throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/" + name + ".jar");
-      url = JarUtils.createJarURL(url);
-      return new JarContext(url);
-   }
-
-   protected VFSContext getParentVFSContext() throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/");
-      return new FileSystemContext(url);
-   }
-
-   /**
-    * Create vfs context from url.
-    *
-    * @param url the url
-    * @return new vfs context
-    * @throws Exception for any error
-    */
-   protected VFSContext createVSFContext(URL url) throws Exception
-   {
-      if (url.toExternalForm().startsWith("jar") == false)
-         url = JarUtils.createJarURL(url);
-      return new JarContext(url);
-   }
-
-   protected String getSuffix()
-   {
-      return ".jar";
-   }
-
-   /**
-    * Was having problems with a jar entry as root of VFS.
-    *
-    * @throws Exception for any error
-    */
-   public void testJarEntryAsRoot() throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/simple.jar");
-      URL entry = new URL("jar:" + url.toString() + "!/child");
-      //entry.openStream().close();
-      VFSContext context = createVSFContext(entry);
-      assertEquals("child", context.getRoot().getName());
-
-      url = getResource("/vfs/test/outer.jar");
-      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
-      //entry.openStream().close();
-      context = createVSFContext(entry);
-      assertEquals("jar2.jar", context.getRoot().getName());
-   }
-
-   /**
-    * Was having problems with a jar entry as root of VFS.
-    * A JarEntry that is the root of the VFS should have a VFS Path of ""
-    *
-    * @throws Exception for any error
-    */
-   public void testPathIsEmptryForJarEntryAsRoot() throws Exception
-   {
-      VFS.init();
-      URL url = getResource("/vfs/context/jar/simple.jar");
-      URL entry = new URL("jar:" + url.toString() + "!/child");
-      //entry.openStream().close();
-      VFSContext context = createVSFContext(entry);
-      assertEquals("child", context.getRoot().getName());
-      assertEquals("", context.getRoot().getPathName());
-
-      url = getResource("/vfs/test/outer.jar");
-      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
-      //entry.openStream().close();
-      context = createVSFContext(entry);
-      assertEquals("jar2.jar", context.getRoot().getName());
-      assertEquals("", context.getRoot().getPathName());
-   }
-
-   protected static void safeClose(InputStream is)
-   {
-      try
-      {
-         is.close();
-      }
-      catch (Throwable ignore)
-      {
-      }
-   }
-
-   /**
-    * Handler representing a directory must return a zero length stream
-    *
-    * This behavior has changed with vfszip - where directory entry within
-    * zip archive when opened as stream returns a recomposed zip archive
-    * that has requested entry as its root
-    *
-    * @throws Exception for any error
-    */
-   public void testDirectoryZipEntryOpenStream() throws Exception
-   {
-      doDirectoryZipEntryOpenStream(true);
-   }
-
-   protected void doDirectoryZipEntryOpenStream(boolean expectEmpty) throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/complex.jar");
-      VFSContext ctx = createVSFContext(url);
-
-      VirtualFileHandler sub = ctx.getRoot().getChild("subfolder");
-      InputStream is = sub.openStream();
-      try
-      {
-         // JBVFS-57 JarInputStream composition - recomposes directory as a
-         // jar equivalent to jar:complex.jar!/subfolder
-         // NOT IMPLEMENTED for vfsjar - vfsjar is deprecated
-         if (expectEmpty)
-            assertTrue("input stream should be closed", is.read() == -1);
-         else
-            assertTrue("input stream should not be empty", is.read() != -1);
-      }
-      finally
-      {
-         safeClose(is);
-      }
-   }
-
-   /**
-    * There was a problem with noCopy inner jars returning empty streams
-    *
-    * @throws Exception for any error
-    */
-   public void testInnerJarFileEntryOpenStream() throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/nested.jar");
-      VFSContext ctx = createVSFContext(url);
-
-      VirtualFileHandler nested = ctx.getRoot().getChild("complex.jar");
-      VirtualFileHandler target = nested.getChild("META-INF/MANIFEST.MF");
-
-      InputStream is = target.openStream();
-      try
-      {
-         assertFalse("input stream closed", is.read() == -1);
-      }
-      finally
-      {
-         safeClose(is);
-      }
-   }
-
-   public void testInnerJarOverURL() throws Exception
-   {
-      URL url = getResource("/vfs/test/nested/" + getNestedName() + ".jar");
-      String urlString = url.toExternalForm();
-      testInnerEntryOverURL(urlString, "/complex.jar", false);
-      // test children
-      testInnerEntryOverURL(urlString, "/complex.jar/child", false);
-      testInnerEntryOverURL(urlString, "/complex.jar/subfolder/subchild", false);
-      // test folder
-      testInnerEntryOverURL(urlString, "/complex.jar/subfolder", false);
-      testInnerEntryOverURL(urlString, "/complex.jar/subfolder/subsubfolder", false);
-      // 3 level zips
-      url = getResource("/vfs/test/level1.zip");
-      urlString = url.toExternalForm();
-      testInnerEntryOverURL(urlString, "/level2.zip/level3.zip/test3.txt", false);
-   }
-
-   protected void testInnerEntryOverURL(String urlString, String entry, boolean result) throws IOException
-   {
-      URL vfsURL = new URL(getProtocol() + urlString.substring(4) + entry);
-      InputStream is = vfsURL.openStream();
-      try
-      {
-         assertEquals("cannot read input stream", result, is.read() == -1);
-      }
-      finally
-      {
-         safeClose(is);
-      }
-   }
-
-   @SuppressWarnings("deprecation")
-   public void testEqualsOnEmptyPath() throws Exception
-   {
-      URL rootURL = getResource("/vfs/test/interop_W2JREMarshallTest_appclient_vehicle.ear");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile file = vfs.findChild("interop_W2JREMarshallTest_appclient_vehicle_client.jar");
-      VirtualFile same = file.findChild("");
-      assertEquals(file, same);
-   }
-
-   /** All of the following entries should be seen
-[551][valkyrie: web_pkg_scope]$ jar -tvf war/target/web_pkg_scope_web.war 
-     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/
-   126 Fri Sep 05 12:47:28 PDT 2008 META-INF/MANIFEST.MF
-     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/
-     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/
-     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/
-     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/entity/
-     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/servlet/
-   288 Fri Sep 05 12:07:30 PDT 2008 WEB-INF/classes/web_pkg_scope/entity/Account.class
-   299 Fri Sep 05 12:07:30 PDT 2008 WEB-INF/classes/web_pkg_scope/servlet/JpaServlet.class
-  1055 Fri Sep 05 12:25:02 PDT 2008 WEB-INF/web.xml
-     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/
-     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/org.jboss.vfs/
-     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/
-   735 Fri Sep 05 12:47:20 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/pom.xml
-   122 Fri Sep 05 12:47:28 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/pom.properties
-    * @throws Exception
-    */
-   public void testWarClassesJarInputStream() throws Exception
-   {
-      URL rootURL = getResource("/vfs/test/web_pkg_scope.ear");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile file = vfs.getChild("web_pkg_scope_web.war/WEB-INF/classes/META-INF/persistence.xml");
-      assertNotNull(file);
-      VirtualFile classes = file.getParent().getParent();
-      // Access the classes contents as a jar file
-      String[] entryNames = {
-            "web_pkg_scope/",
-            "web_pkg_scope/entity/",
-            "web_pkg_scope/servlet/",
-            "web_pkg_scope/entity/Account.class",
-            "web_pkg_scope/servlet/JpaServlet.class",
-            // JarInputStream never returns META-INF/ entry - it just skips it
-            // "META-INF/",
-            "META-INF/persistence.xml"
-      };
-
-      URL [] classesURLs = new URL []
-      {
-         classes.toURL(),
-         new URL(classes.toURL() + "?" + VFSUtils.USE_COPY_QUERY + "=true")
-      };
-
-      for (URL url: classesURLs)
-      {
-         JarInputStream jis = new JarInputStream( url.openStream() );
-         HashSet<String> missingEntries = new HashSet<String>(Arrays.asList(entryNames));
-         Set<String> excess = new HashSet<String>();
-         JarEntry jarEntry;
-         while((jarEntry = jis.getNextJarEntry()) != null)
-         {
-            String name = jarEntry.getName();
-            boolean removed = missingEntries.remove(name);
-            if(!removed)
-               excess.add(name);
-         }
-         assertEquals("No missing entries: "+missingEntries, 0, missingEntries.size());
-         assertEquals("Excess entries: " + excess, 0, excess.size());
-      }
-      classes.closeStreams();
-   }
-
-   // we need to make sure this doesn't get touched before
-   protected String getNestedName()
-   {
-      return "nested";
-   }
-
-   protected String getProtocol()
-   {
-      return "vfsfile";
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/JARVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,347 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.jar.JarContext;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * JARVFSContextUnitTestCase.
+ *
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 1.1 $
+ */
+public class JARVFSContextUnitTestCase extends AbstractVFSContextTest
+{
+   public JARVFSContextUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      VFS.init();
+      System.out.println("java.protocol.handler.pkgs: " + System.getProperty("java.protocol.handler.pkgs"));
+      return new TestSuite(JARVFSContextUnitTestCase.class);
+   }
+
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/" + name + ".jar");
+      url = JarUtils.createJarURL(url);
+      return new JarContext(url);
+   }
+
+   protected VFSContext getParentVFSContext() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/");
+      return new FileSystemContext(url);
+   }
+
+   /**
+    * Create vfs context from url.
+    *
+    * @param url the url
+    * @return new vfs context
+    * @throws Exception for any error
+    */
+   protected VFSContext createVSFContext(URL url) throws Exception
+   {
+      if (url.toExternalForm().startsWith("jar") == false)
+         url = JarUtils.createJarURL(url);
+      return new JarContext(url);
+   }
+
+   protected String getSuffix()
+   {
+      return ".jar";
+   }
+
+   protected String getRealProtocol()
+   {
+      return "jar:file";
+   }
+
+   protected String getRealURLEnd()
+   {
+      return "!/";
+   }
+
+   protected String transformExpectedEnd(String expecetedEnd)
+   {
+      return expecetedEnd;
+   }
+
+   protected boolean isRealURLSupported()
+   {
+      return false;
+   }
+
+   /**
+    * Was having problems with a jar entry as root of VFS.
+    *
+    * @throws Exception for any error
+    */
+   public void testJarEntryAsRoot() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/simple.jar");
+      URL entry = new URL("jar:" + url.toString() + "!/child");
+      //entry.openStream().close();
+      VFSContext context = createVSFContext(entry);
+      assertEquals("child", context.getRoot().getName());
+
+      url = getResource("/vfs/test/outer.jar");
+      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
+      //entry.openStream().close();
+      context = createVSFContext(entry);
+      assertEquals("jar2.jar", context.getRoot().getName());
+   }
+
+   /**
+    * Was having problems with a jar entry as root of VFS.
+    * A JarEntry that is the root of the VFS should have a VFS Path of ""
+    *
+    * @throws Exception for any error
+    */
+   public void testPathIsEmptryForJarEntryAsRoot() throws Exception
+   {
+      VFS.init();
+      URL url = getResource("/vfs/context/jar/simple.jar");
+      URL entry = new URL("jar:" + url.toString() + "!/child");
+      //entry.openStream().close();
+      VFSContext context = createVSFContext(entry);
+      assertEquals("child", context.getRoot().getName());
+      assertEquals("", context.getRoot().getPathName());
+
+      url = getResource("/vfs/test/outer.jar");
+      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
+      //entry.openStream().close();
+      context = createVSFContext(entry);
+      assertEquals("jar2.jar", context.getRoot().getName());
+      assertEquals("", context.getRoot().getPathName());
+   }
+
+   protected static void safeClose(InputStream is)
+   {
+      try
+      {
+         is.close();
+      }
+      catch (Throwable ignore)
+      {
+      }
+   }
+
+   /**
+    * Handler representing a directory must return a zero length stream
+    *
+    * This behavior has changed with vfszip - where directory entry within
+    * zip archive when opened as stream returns a recomposed zip archive
+    * that has requested entry as its root
+    *
+    * @throws Exception for any error
+    */
+   public void testDirectoryZipEntryOpenStream() throws Exception
+   {
+      doDirectoryZipEntryOpenStream(true);
+   }
+
+   protected void doDirectoryZipEntryOpenStream(boolean expectEmpty) throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/complex.jar");
+      VFSContext ctx = createVSFContext(url);
+
+      VirtualFileHandler sub = ctx.getRoot().getChild("subfolder");
+      InputStream is = sub.openStream();
+      try
+      {
+         // JBVFS-57 JarInputStream composition - recomposes directory as a
+         // jar equivalent to jar:complex.jar!/subfolder
+         // NOT IMPLEMENTED for vfsjar - vfsjar is deprecated
+         if (expectEmpty)
+            assertTrue("input stream should be closed", is.read() == -1);
+         else
+            assertTrue("input stream should not be empty", is.read() != -1);
+      }
+      finally
+      {
+         safeClose(is);
+      }
+   }
+
+   /**
+    * There was a problem with noCopy inner jars returning empty streams
+    *
+    * @throws Exception for any error
+    */
+   public void testInnerJarFileEntryOpenStream() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/nested.jar");
+      VFSContext ctx = createVSFContext(url);
+
+      VirtualFileHandler nested = ctx.getRoot().getChild("complex.jar");
+      VirtualFileHandler target = nested.getChild("META-INF/MANIFEST.MF");
+
+      InputStream is = target.openStream();
+      try
+      {
+         assertFalse("input stream closed", is.read() == -1);
+      }
+      finally
+      {
+         safeClose(is);
+      }
+   }
+
+   public void testInnerJarOverURL() throws Exception
+   {
+      URL url = getResource("/vfs/test/nested/" + getNestedName() + ".jar");
+      String urlString = url.toExternalForm();
+      testInnerEntryOverURL(urlString, "/complex.jar", false);
+      // test children
+      testInnerEntryOverURL(urlString, "/complex.jar/child", false);
+      testInnerEntryOverURL(urlString, "/complex.jar/subfolder/subchild", false);
+      // test folder
+      testInnerEntryOverURL(urlString, "/complex.jar/subfolder", false);
+      testInnerEntryOverURL(urlString, "/complex.jar/subfolder/subsubfolder", false);
+      // 3 level zips
+      url = getResource("/vfs/test/level1.zip");
+      urlString = url.toExternalForm();
+      testInnerEntryOverURL(urlString, "/level2.zip/level3.zip/test3.txt", false);
+   }
+
+   protected void testInnerEntryOverURL(String urlString, String entry, boolean result) throws IOException
+   {
+      URL vfsURL = new URL(getProtocol() + urlString.substring(4) + entry);
+      InputStream is = vfsURL.openStream();
+      try
+      {
+         assertEquals("cannot read input stream", result, is.read() == -1);
+      }
+      finally
+      {
+         safeClose(is);
+      }
+   }
+
+   @SuppressWarnings("deprecation")
+   public void testEqualsOnEmptyPath() throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/interop_W2JREMarshallTest_appclient_vehicle.ear");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile file = vfs.findChild("interop_W2JREMarshallTest_appclient_vehicle_client.jar");
+      VirtualFile same = file.findChild("");
+      assertEquals(file, same);
+   }
+
+   /** All of the following entries should be seen
+[551][valkyrie: web_pkg_scope]$ jar -tvf war/target/web_pkg_scope_web.war 
+     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/
+   126 Fri Sep 05 12:47:28 PDT 2008 META-INF/MANIFEST.MF
+     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/
+     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/
+     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/
+     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/entity/
+     0 Fri Sep 05 12:07:32 PDT 2008 WEB-INF/classes/web_pkg_scope/servlet/
+   288 Fri Sep 05 12:07:30 PDT 2008 WEB-INF/classes/web_pkg_scope/entity/Account.class
+   299 Fri Sep 05 12:07:30 PDT 2008 WEB-INF/classes/web_pkg_scope/servlet/JpaServlet.class
+  1055 Fri Sep 05 12:25:02 PDT 2008 WEB-INF/web.xml
+     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/
+     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/org.jboss.vfs/
+     0 Fri Sep 05 12:47:30 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/
+   735 Fri Sep 05 12:47:20 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/pom.xml
+   122 Fri Sep 05 12:47:28 PDT 2008 META-INF/maven/org.jboss.vfs/web_pkg_scope_web/pom.properties
+    * @throws Exception
+    */
+   public void testWarClassesJarInputStream() throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/web_pkg_scope.ear");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile file = vfs.getChild("web_pkg_scope_web.war/WEB-INF/classes/META-INF/persistence.xml");
+      assertNotNull(file);
+      VirtualFile classes = file.getParent().getParent();
+      // Access the classes contents as a jar file
+      String[] entryNames = {
+            "web_pkg_scope/",
+            "web_pkg_scope/entity/",
+            "web_pkg_scope/servlet/",
+            "web_pkg_scope/entity/Account.class",
+            "web_pkg_scope/servlet/JpaServlet.class",
+            // JarInputStream never returns META-INF/ entry - it just skips it
+            // "META-INF/",
+            "META-INF/persistence.xml"
+      };
+
+      URL [] classesURLs = new URL []
+      {
+         classes.toURL(),
+         new URL(classes.toURL() + "?" + VFSUtils.USE_COPY_QUERY + "=true")
+      };
+
+      for (URL url: classesURLs)
+      {
+         JarInputStream jis = new JarInputStream( url.openStream() );
+         HashSet<String> missingEntries = new HashSet<String>(Arrays.asList(entryNames));
+         Set<String> excess = new HashSet<String>();
+         JarEntry jarEntry;
+         while((jarEntry = jis.getNextJarEntry()) != null)
+         {
+            String name = jarEntry.getName();
+            boolean removed = missingEntries.remove(name);
+            if(!removed)
+               excess.add(name);
+         }
+         assertEquals("No missing entries: "+missingEntries, 0, missingEntries.size());
+         assertEquals("Excess entries: " + excess, 0, excess.size());
+      }
+      classes.closeStreams();
+   }
+
+   // we need to make sure this doesn't get touched before
+   protected String getNestedName()
+   {
+      return "nested";
+   }
+
+   protected String getProtocol()
+   {
+      return "vfsfile";
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,49 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import junit.framework.Test;
-import org.jboss.virtual.plugins.cache.LRUVFSCache;
-import org.jboss.virtual.spi.cache.VFSCache;
-
-/**
- * LRU VFSCache Test.
- *
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- */
-public class LRUCacheTestCase extends CachePolicyVFSCacheTest
-{
-   public LRUCacheTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return suite(LRUCacheTestCase.class);
-   }
-
-   protected VFSCache createCache()
-   {
-      return new LRUVFSCache(2, 10);
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java (from rev 80639, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/LRUCacheTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,69 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.cache.LRUVFSCache;
+import org.jboss.virtual.spi.cache.VFSCache;
+
+/**
+ * LRU VFSCache Test.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ */
+public class LRUCacheTestCase extends CachePolicyVFSCacheTest
+{
+   public LRUCacheTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(LRUCacheTestCase.class);
+   }
+
+   protected VFSCache createCache()
+   {
+      return new LRUVFSCache(2, 10);
+   }
+
+   protected Iterable<String> populateRequiredSystemProperties()
+   {
+      System.setProperty(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.min", "2");
+      System.setProperty(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.max", "10");      
+      return Arrays.asList(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.min", VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.max");
+   }
+
+   protected Map<Object, Object> getMap()
+   {
+      Map<Object, Object> map = new HashMap<Object, Object>();
+      map.put(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.min", 2);
+      map.put(VFSUtils.VFS_CACHE_KEY + ".LRUPolicyCaching.max", 10);
+      return map;
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,43 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * Map VFSCache Test.
- *
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class MapVFSCacheTest extends VFSCacheTest
-{
-   public MapVFSCacheTest(String name)
-   {
-      super(name);
-   }
-
-   protected void testCachedContexts(Iterable<VFSContext> iter)
-   {
-      VFSContext context = iter.iterator().next();
-      assertNotNull(context);
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java (from rev 80639, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/MapVFSCacheTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,50 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.util.Map;
+
+import org.jboss.virtual.spi.VFSContext;
+
+/**
+ * Map VFSCache Test.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class MapVFSCacheTest extends VFSCacheTest
+{
+   public MapVFSCacheTest(String name)
+   {
+      super(name);
+   }
+
+   protected Map<Object, Object> getMap()
+   {
+      return null;
+   }
+
+   protected void testCachedContexts(Iterable<VFSContext> iter)
+   {
+      VFSContext context = iter.iterator().next();
+      assertNotNull(context);
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,106 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.IOException;
-import java.net.URL;
-
-import junit.framework.Test;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-
-/**
- * Test path tokens.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class PathTokensTestCase extends AbstractVFSTest
-{
-   public PathTokensTestCase(String s)
-   {
-      super(s);
-   }
-
-   public static Test suite()
-   {
-      return suite(PathTokensTestCase.class);
-   }
-
-   protected VirtualFile testPath(String path) throws IOException
-   {
-      return testPath("/vfs", path);
-   }
-
-   protected VirtualFile testPath(String context, String path) throws IOException
-   {
-      URL url = getResource(context);
-      VirtualFile vf = VFS.getRoot(url);
-      return vf.getChild(path);
-   }
-
-   protected void testValidPath(String path) throws Throwable
-   {
-      assertNotNull("No such path: " + path, testPath(path));
-   }
-
-   protected void testBrokenPath(String path) throws Throwable
-   {
-      try
-      {
-         testPath(path);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         assertInstanceOf(t, IllegalArgumentException.class, false);
-      }
-   }
-
-   public void testSpecialTokens() throws Throwable
-   {
-      testBrokenPath("/.../");
-      testBrokenPath(".../");
-      testBrokenPath("/...");
-      testBrokenPath("...");
-      testBrokenPath("/..somemorepath/");
-      testBrokenPath("..somemorepath/");
-      testBrokenPath("/..somemorepath");
-      testBrokenPath("..somemorepath");
-      }
-
-   public void testRepeatedSlashes() throws Throwable
-   {
-      testValidPath("/");
-      testValidPath("//");
-      testValidPath("///");
-      testValidPath("////");
-      testValidPath("//context");
-      testValidPath("//context//");
-      testValidPath("context//file");
-      testValidPath("context///file");
-      testValidPath("//context//file");
-      testValidPath("//context///file");
-      testValidPath("//context////file");
-      testValidPath("//context///jar//");
-      testValidPath("//context///jar///");
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/PathTokensTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,146 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import java.util.Arrays;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
+
+/**
+ * Test path tokens.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class PathTokensTestCase extends AbstractVFSTest
+{
+   public PathTokensTestCase(String s)
+   {
+      super(s);
+   }
+
+   public static Test suite()
+   {
+      return suite(PathTokensTestCase.class);
+   }
+
+   protected VirtualFile testPath(String path) throws IOException
+   {
+      return testPath("/vfs", path);
+   }
+
+   protected VirtualFile testPath(String context, String path) throws IOException
+   {
+      URL url = getResource(context);
+      VirtualFile vf = VFS.getRoot(url);
+      return vf.getChild(path);
+   }
+
+   protected void testValidPath(String path) throws Throwable
+   {
+      assertNotNull("No such path: " + path, testPath(path));
+   }
+
+   protected void testBrokenPath(String path) throws Throwable
+   {
+      try
+      {
+         testPath(path);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         assertInstanceOf(t, IllegalArgumentException.class, false);
+      }
+   }
+
+   public void testSpecialTokens() throws Throwable
+   {
+      PathTokenizer.setErrorOnSuspiciousTokens(true);
+      try
+      {
+         testBrokenPath("/.../");
+         testBrokenPath(".../");
+         testBrokenPath("/...");
+         testBrokenPath("...");
+         testBrokenPath("/..somemorepath/");
+         testBrokenPath("..somemorepath/");
+         testBrokenPath("/..somemorepath");
+         testBrokenPath("..somemorepath");
+      }
+      finally
+      {
+         PathTokenizer.setErrorOnSuspiciousTokens(false);
+      }
+   }
+
+   public void testRepeatedSlashes() throws Throwable
+   {
+      testValidPath("/");
+      testValidPath("//");
+      testValidPath("///");
+      testValidPath("////");
+      testValidPath("//context");
+      testValidPath("//context//");
+      testValidPath("context//file");
+      testValidPath("context///file");
+      testValidPath("//context//file");
+      testValidPath("//context///file");
+      testValidPath("//context////file");
+      testValidPath("//context///jar//");
+      testValidPath("//context///jar///");
+   }
+
+   public void testSuspiciousTokens() throws Throwable
+   {
+      testSuspiciousTokens(false);
+      testSuspiciousTokens(true);      
+   }
+
+   public void testSuspiciousTokens(boolean flag) throws Throwable
+   {
+      PathTokenizer.setErrorOnSuspiciousTokens(flag);
+      try
+      {
+         String path = "/.hudson/..hudson/...hudson/./../.../.*foo/foo.bar";
+         List<String> tokens = PathTokenizer.getTokens(path);
+         List<String> expected = Arrays.asList(".hudson", "..hudson", "...hudson", ".", "..", "...", ".*foo", "foo.bar");
+         assertEquals(expected, tokens);
+         if (flag)
+            fail("Should not be here.");
+      }
+      catch (Throwable t)
+      {
+         if (!flag)
+            throw t;
+      }
+      finally
+      {
+         PathTokenizer.setErrorOnSuspiciousTokens(!flag);
+      }
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,49 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import org.jboss.virtual.plugins.cache.TimedVFSCache;
-import org.jboss.virtual.spi.cache.VFSCache;
-import junit.framework.Test;
-
-/**
- * Timed VFSCache Test.
- *
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- */
-public class TimedCacheTestCase extends CachePolicyVFSCacheTest
-{
-   public TimedCacheTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return suite(TimedCacheTestCase.class);
-   }
-
-   protected VFSCache createCache()
-   {
-      return new TimedVFSCache(60);
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/TimedCacheTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,67 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import org.jboss.virtual.plugins.cache.TimedVFSCache;
+import org.jboss.virtual.spi.cache.VFSCache;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.VFSUtils;
+import junit.framework.Test;
+
+/**
+ * Timed VFSCache Test.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ */
+public class TimedCacheTestCase extends CachePolicyVFSCacheTest
+{
+   public TimedCacheTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(TimedCacheTestCase.class);
+   }
+
+   protected VFSCache createCache()
+   {
+      return new TimedVFSCache(5);
+   }
+
+   protected void testCachedContexts(Iterable<VFSContext> iter)
+   {
+      VFSContext context = iter.iterator().next();
+      assertNotNull(context);
+   }
+
+   protected Map<Object, Object> getMap()
+   {
+      Map<Object, Object> map = new HashMap<Object, Object>();
+      map.put(VFSUtils.VFS_CACHE_KEY + ".TimedPolicyCaching.lifetime", 5);
+      return map;
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,97 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2005, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import junit.textui.TestRunner;
-import org.jboss.virtual.VFS;
-
-/**
- * VFS All Test Suite.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- * @version $Revision: 46146 $
- */
-public class VFSAllTestSuite extends TestSuite
-{
-   public static void main(String[] args)
-   {
-      TestRunner.run(suite());
-   }
-
-   public static Test suite()
-   {
-      VFS.init();
-      TestSuite suite = new TestSuite("VFS Tests default");
-
-      // vfs / spi
-      suite.addTest(VFSUnitTestCase.suite());
-      suite.addTest(VirtualFileUnitTestCase.suite());
-      // url
-      suite.addTest(URLResolutionUnitTestCase.suite());
-      suite.addTest(URLExistsUnitTestCase.suite());
-      suite.addTest(URLConnectionUnitTestCase.suite());
-      // files
-      suite.addTest(FileVFSUnitTestCase.suite());
-      suite.addTest(CopyFileVFSUnitTestCase.suite());
-      suite.addTest(FileVFSContextUnitTestCase.suite());
-      suite.addTest(FileVirtualFileHandlerUnitTestCase.suite());
-      // jars
-      suite.addTest(JARCacheUnitTestCase.suite());
-      suite.addTest(CopyJARCacheUnitTestCase.suite());
-      suite.addTest(JARVFSContextUnitTestCase.suite());
-      suite.addTest(JARVirtualFileHandlerUnitTestCase.suite());
-      suite.addTest(JARSerializationUnitTestCase.suite());
-      suite.addTest(CopyJARSerializationUnitTestCase.suite());
-      suite.addTest(JAREntryTestCase.suite());
-      suite.addTest(CopyJAREntryTestCase.suite());
-      suite.addTest(ZipEntryHandlerUnitTestCase.suite());
-      suite.addTest(ZipEntryVFSContextUnitTestCase.suite());
-      // contexts
-      suite.addTest(AssembledContextTestCase.suite());
-      suite.addTest(MemoryTestCase.suite());
-      suite.addTest(SundryVFSUnitTestCase.suite());
-      // options / policy / path
-      suite.addTest(PathQueryTestCase.suite());
-      suite.addTest(PathTokensTestCase.suite());
-      // unpack
-      suite.addTest(UnpackTestCase.suite());
-      suite.addTest(ExplodeTestCase.suite());
-      suite.addTest(TempTestCase.suite());
-      // visitor
-      suite.addTest(VisitorUnitTestCase.suite());
-      // utils
-      suite.addTest(VFSUtilTestCase.suite());
-      // custom
-      suite.addTest(CustomTestCase.suite());
-      suite.addTest(VFSResourceTestCase.suite());
-      // cache
-      suite.addTest(LRUCacheTestCase.suite());
-      suite.addTest(TimedCacheTestCase.suite());
-      suite.addTest(SoftRefCacheTestCase.suite());
-      suite.addTest(WeakRefCacheTestCase.suite());
-
-      return suite;
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,100 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+import org.jboss.virtual.VFS;
+
+/**
+ * VFS All Test Suite.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @version $Revision: 46146 $
+ */
+public class VFSAllTestSuite extends TestSuite
+{
+   public static void main(String[] args)
+   {
+      TestRunner.run(suite());
+   }
+
+   public static Test suite()
+   {
+      VFS.init();
+      TestSuite suite = new TestSuite("VFS Tests default");
+
+      // vfs / spi
+      suite.addTest(VFSUnitTestCase.suite());
+      suite.addTest(VirtualFileUnitTestCase.suite());
+      // url
+      suite.addTest(URLResolutionUnitTestCase.suite());
+      suite.addTest(URLExistsUnitTestCase.suite());
+      suite.addTest(URLConnectionUnitTestCase.suite());
+      // files
+      suite.addTest(FileVFSUnitTestCase.suite());
+      suite.addTest(CopyFileVFSUnitTestCase.suite());
+      suite.addTest(FileVFSContextUnitTestCase.suite());
+      suite.addTest(FileVirtualFileHandlerUnitTestCase.suite());
+      // jars
+      suite.addTest(JARCacheUnitTestCase.suite());
+      suite.addTest(CopyJARCacheUnitTestCase.suite());
+      suite.addTest(JARVFSContextUnitTestCase.suite());
+      suite.addTest(JARVirtualFileHandlerUnitTestCase.suite());
+      suite.addTest(JARSerializationUnitTestCase.suite());
+      suite.addTest(CopyJARSerializationUnitTestCase.suite());
+      suite.addTest(JAREntryTestCase.suite());
+      suite.addTest(CopyJAREntryTestCase.suite());
+      suite.addTest(ZipEntryHandlerUnitTestCase.suite());
+      suite.addTest(ZipEntryVFSContextUnitTestCase.suite());
+      // contexts
+      suite.addTest(AssembledContextTestCase.suite());
+      suite.addTest(MemoryTestCase.suite());
+      suite.addTest(SundryVFSUnitTestCase.suite());
+      // options / policy / path
+      suite.addTest(PathQueryTestCase.suite());
+      suite.addTest(PathTokensTestCase.suite());
+      // unpack
+      suite.addTest(UnpackTestCase.suite());
+      suite.addTest(ExplodeTestCase.suite());
+      suite.addTest(TempTestCase.suite());
+      // visitor
+      suite.addTest(VisitorUnitTestCase.suite());
+      // utils
+      suite.addTest(VFSUtilTestCase.suite());
+      // custom
+      suite.addTest(CustomTestCase.suite());
+      suite.addTest(VFSResourceTestCase.suite());
+      // cache
+      suite.addTest(LRUCacheTestCase.suite());
+      suite.addTest(TimedCacheTestCase.suite());
+      suite.addTest(IterableTimedCacheTestCase.suite());
+      suite.addTest(SoftRefCacheTestCase.suite());
+      suite.addTest(WeakRefCacheTestCase.suite());
+      // exception handler
+      suite.addTest(ExceptionHandlerTestCase.suite());
+
+      return suite;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,166 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.spi.cache.VFSCache;
-import org.jboss.virtual.spi.cache.VFSCacheFactory;
-import org.jboss.virtual.spi.cache.CacheStatistics;
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * VFSCache Test.
- *
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- */
-public abstract class VFSCacheTest extends AbstractVFSTest
-{
-   public VFSCacheTest(String name)
-   {
-      super(name);
-   }
-
-   protected abstract VFSCache createCache();
-
-   @SuppressWarnings("deprecation")
-   public void testCache() throws Exception
-   {
-      URL url = getResource("/vfs/test/nested");
-
-      VFSCache cache = createCache();
-      cache.start();
-      try
-      {
-         VFSCacheFactory.setInstance(cache);
-         try
-         {
-            VirtualFile root = VFS.getRoot(url);
-
-            VirtualFile file = root.findChild("/nested.jar/META-INF/empty.txt");
-            URL fileURL = file.toURL();
-            VirtualFile nested = root.findChild("/nested.jar/complex.jar/subfolder/subsubfolder/subsubchild");
-            URL nestedURL = nested.toURL();
-
-            assertEquals(file, cache.getFile(fileURL));
-            assertEquals(nested, cache.getFile(nestedURL));
-
-            VFSCacheFactory.setInstance(null);
-            VFSCache wrapper = new WrapperVFSCache(cache);
-            VFSCacheFactory.setInstance(wrapper);
-
-            assertEquals(file, wrapper.getFile(fileURL));
-            assertEquals(nested, wrapper.getFile(nestedURL));
-         }
-         finally
-         {
-            VFSCacheFactory.setInstance(null);
-         }
-      }
-      finally
-      {
-         cache.stop();
-      }
-   }
-
-   protected abstract void testCachedContexts(Iterable<VFSContext> iter);
-
-   public void testCacheStatistics() throws Exception
-   {
-      URL url = getResource("/vfs/test/nested");
-
-      VFSCache cache = createCache();
-      cache.start();
-      try
-      {
-         if (cache instanceof CacheStatistics)
-         {
-            CacheStatistics statistics = CacheStatistics.class.cast(cache);
-            VFSCacheFactory.setInstance(cache);
-            try
-            {
-               VirtualFile root = VFS.getRoot(url);
-               assertNotNull(root);
-
-               Iterable<VFSContext> iter = statistics.getCachedContexts();
-               testCachedContexts(iter);
-
-               assertEquals(1, statistics.size());
-               assertTrue(statistics.lastInsert() != 0);
-            }
-            finally
-            {
-               VFSCacheFactory.setInstance(null);
-            }
-         }
-      }
-      finally
-      {
-         cache.stop();
-      }
-   }
-
-   private class WrapperVFSCache implements VFSCache
-   {
-      private VFSCache delegate;
-
-      private WrapperVFSCache(VFSCache delegate)
-      {
-         this.delegate = delegate;
-      }
-
-      public VirtualFile getFile(URI uri) throws IOException
-      {
-         return delegate.getFile(uri);
-      }
-
-      public VirtualFile getFile(URL url) throws IOException
-      {
-         return delegate.getFile(url);
-      }
-
-      public void putContext(VFSContext context)
-      {
-         throw new IllegalArgumentException("Context should already be there: " + context);
-      }
-
-      public void removeContext(VFSContext context)
-      {
-      }
-
-      public void start() throws Exception
-      {
-      }
-
-      public void stop()
-      {
-      }
-
-      public void flush()
-      {
-      }
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java (from rev 80639, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,220 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Map;
+
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.cache.CacheStatistics;
+import org.jboss.virtual.spi.cache.VFSCache;
+import org.jboss.virtual.spi.cache.VFSCacheFactory;
+import org.jboss.virtual.spi.cache.helpers.NoopVFSCache;
+
+/**
+ * VFSCache Test.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ */
+public abstract class VFSCacheTest extends AbstractVFSTest
+{
+   public VFSCacheTest(String name)
+   {
+      super(name);
+   }
+
+   protected abstract VFSCache createCache();
+
+   @SuppressWarnings("deprecation")
+   public void testCache() throws Exception
+   {
+      URL url = getResource("/vfs/test/nested");
+
+      VFSCache cache = createCache();
+      cache.start();
+      try
+      {
+         VFSCacheFactory.setInstance(cache);
+         try
+         {
+            VirtualFile root = VFS.getRoot(url);
+
+            VirtualFile file = root.findChild("/nested.jar/META-INF/empty.txt");
+            URL fileURL = file.toURL();
+            VirtualFile nested = root.findChild("/nested.jar/complex.jar/subfolder/subsubfolder/subsubchild");
+            URL nestedURL = nested.toURL();
+
+            assertEquals(file, cache.getFile(fileURL));
+            assertEquals(nested, cache.getFile(nestedURL));
+
+            VFSCacheFactory.setInstance(null);
+            VFSCache wrapper = new WrapperVFSCache(cache);
+            VFSCacheFactory.setInstance(wrapper);
+
+            assertEquals(file, wrapper.getFile(fileURL));
+            assertEquals(nested, wrapper.getFile(nestedURL));
+         }
+         finally
+         {
+            VFSCacheFactory.setInstance(null);
+         }
+      }
+      finally
+      {
+         cache.stop();
+      }
+   }
+
+   protected abstract void testCachedContexts(Iterable<VFSContext> iter);
+
+   public void testCacheStatistics() throws Exception
+   {
+      URL url = getResource("/vfs/test/nested");
+
+      VFSCache cache = createCache();
+      cache.start();
+      try
+      {
+         if (cache instanceof CacheStatistics)
+         {
+            CacheStatistics statistics = CacheStatistics.class.cast(cache);
+            VFSCacheFactory.setInstance(cache);
+            try
+            {
+               VirtualFile root = VFS.getRoot(url);
+               assertNotNull(root);
+
+               Iterable<VFSContext> iter = statistics.getCachedContexts();
+               testCachedContexts(iter);
+
+               assertEquals(1, statistics.size());
+               assertTrue(statistics.lastInsert() != 0);
+            }
+            finally
+            {
+               VFSCacheFactory.setInstance(null);
+            }
+         }
+      }
+      finally
+      {
+         cache.stop();
+      }
+   }
+
+   protected Class<? extends VFSCache> getCacheClass()
+   {
+      VFSCache cache = createCache();
+      return cache.getClass();
+   }
+
+   protected Iterable<String> populateRequiredSystemProperties()
+   {
+      return Collections.emptySet();
+   }
+
+   protected abstract Map<Object, Object> getMap();
+
+   public void testCacheFactory() throws Exception
+   {
+      VFSCache cache;
+      String cacheClassName = getCacheClass().getName();
+
+      VFSCacheFactory.setInstance(null);
+      try
+      {
+         Iterable<String> keys = populateRequiredSystemProperties();
+         try
+         {
+            cache = VFSCacheFactory.getInstance(cacheClassName);
+            assertNotNull(cache);
+            assertTrue(cache instanceof NoopVFSCache == false);
+            cache.flush();
+         }
+         finally
+         {
+            for (String key : keys)
+               System.clearProperty(key);
+         }
+
+         VFSCacheFactory.setInstance(null);
+
+         VFSCache mapParamCache = VFSCacheFactory.getInstance(cacheClassName, getMap());
+         // need new instance, so we know we're really testing map parameter
+         assertNotSame(cache, mapParamCache);
+         cache = mapParamCache;
+         assertNotNull(cache);
+         assertTrue(cache instanceof NoopVFSCache == false);
+         cache.flush();
+      }
+      finally
+      {
+         VFSCacheFactory.setInstance(null);
+      }
+   }
+
+   private class WrapperVFSCache implements VFSCache
+   {
+      private VFSCache delegate;
+
+      private WrapperVFSCache(VFSCache delegate)
+      {
+         this.delegate = delegate;
+      }
+
+      public VirtualFile getFile(URI uri) throws IOException
+      {
+         return delegate.getFile(uri);
+      }
+
+      public VirtualFile getFile(URL url) throws IOException
+      {
+         return delegate.getFile(url);
+      }
+
+      public void putContext(VFSContext context)
+      {
+         throw new IllegalArgumentException("Context should already be there: " + context);
+      }
+
+      public void removeContext(VFSContext context)
+      {
+      }
+
+      public void start() throws Exception
+      {
+      }
+
+      public void stop()
+      {
+      }
+
+      public void flush()
+      {
+      }
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,1365 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.IOException;
-import java.net.URI;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-
-import org.jboss.test.virtual.support.MockURLStreamHandler;
-import org.jboss.test.virtual.support.MockVFSContext;
-import org.jboss.test.virtual.support.MockVirtualFileFilter;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.plugins.vfs.helpers.FilterVirtualFileVisitor;
-
-/**
- * VFSUnitTestCase.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class VFSUnitTestCase extends AbstractMockVFSTest
-{
-   public VFSUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(VFSUnitTestCase.class);
-   }
-
-   public void testGetVFSURI() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      MockVFSContext context2 = registerSimple2VFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertNotNull(vfs);
-      assertEquals(context.getVFS(), vfs);
-      
-      VFS vfs2 = VFS.getVFS(context2.getRootURI());
-      assertNotNull(vfs2);
-      assertEquals(context2.getVFS(), vfs2);
-   }
-
-   public void testGetVFSURINull() throws Exception
-   {
-      try
-      {
-         VFS.getVFS((URI) null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVFSURINoFactory() throws Exception
-   {
-      try
-      {
-         URI uri = new URI("doesnotexist:///");
-         VFS.getVFS(uri);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVFSURIIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      mockVFSContextFactory.setIOException("getVFSURI");
-
-      try
-      {
-         VFS.getVFS(context.getRootURI());
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVFSURL() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      MockVFSContext context2 = registerSimple2VFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURL());
-      assertNotNull(vfs);
-      assertEquals(context.getVFS(), vfs);
-      
-      VFS vfs2 = VFS.getVFS(context2.getRootURL());
-      assertNotNull(vfs2);
-      assertEquals(context2.getVFS(), vfs2);
-   }
-
-   public void testGetVFSURLNull() throws Exception
-   {
-      try
-      {
-         VFS.getVFS((URL) null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVFSURLNoFactory() throws Exception
-   {
-      try
-      {
-         URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
-         VFS.getVFS(url);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVFSURLIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      mockVFSContextFactory.setIOException("getVFSURL");
-
-      try
-      {
-         VFS.getVFS(context.getRootURL());
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURI() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      
-      VirtualFile file = VFS.getRoot(context.getRootURI());
-      assertNotNull(file);
-      assertEquals(context.getRoot().getVirtualFile(), file);
-   }
-
-   public void testGetRootURINullURI() throws Exception
-   {
-      try
-      {
-         VFS.getRoot((URI) null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetRootURINoFactory() throws Exception
-   {
-      try
-      {
-         URI uri = new URI("doesnotexist:///");
-         VFS.getRoot(uri);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURIIOExceptionGetVFS() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      mockVFSContextFactory.setIOException("getVFSURI");
-
-      try
-      {
-         VFS.getRoot(context.getRootURI());
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURIIOExceptionGetRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.setIOException("getRoot");
-
-      try
-      {
-         VFS.getRoot(context.getRootURI());
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURIRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      
-      VirtualFile file = VFS.getVirtualFile(context.getRootURI(), "");
-      assertNotNull(file);
-      assertEquals(context.getRoot().getVirtualFile(), file);
-   }
-
-   public void testGetVirtualFileURIChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VirtualFile file1 = VFS.getVirtualFile(context.getRootURI(), "child1");
-      assertNotNull(file1);
-      assertEquals(child1, file1);
-      
-      VirtualFile file2 = VFS.getVirtualFile(context.getRootURI(), "child2");
-      assertNotNull(file2);
-      assertEquals(child2, file2);
-      
-      VirtualFile file3 = VFS.getVirtualFile(context.getRootURI(), "child3");
-      assertNotNull(file3);
-      assertEquals(child3, file3);
-   }
-
-   public void testGetVirtualFileURINullURI() throws Exception
-   {
-      try
-      {
-         VFS.getVirtualFile((URI) null, "");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURINullPath() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURI(), null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURINoFactory() throws Exception
-   {
-      try
-      {
-         URI uri = new URI("doesnotexist:///");
-         VFS.getVirtualFile(uri, "");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURIDoesNotExist() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURI(), "doesnotexist");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURIIOExceptionGetVFS() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      mockVFSContextFactory.setIOException("getVFSURI");
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURI(), "child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURIIOExceptionFindChild() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChild");
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURI(), "child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURL() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      
-      VirtualFile file = VFS.getRoot(context.getRootURL());
-      assertNotNull(file);
-      assertEquals(context.getRoot().getVirtualFile(), file);
-   }
-
-   public void testGetRootURLNullURL() throws Exception
-   {
-      try
-      {
-         VFS.getRoot((URL) null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetRootURLNoFactory() throws Exception
-   {
-      URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
-      try
-      {
-         VFS.getRoot(url);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURLIOExceptionGetVFS() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      mockVFSContextFactory.setIOException("getVFSURL");
-
-      URL url = context.getRootURL();
-      try
-      {
-         VFS.getRoot(url);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRootURLIOExceptionGetRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.setIOException("getRoot");
-
-      URL url = context.getRootURL();
-      try
-      {
-         VFS.getRoot(url);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      
-      VirtualFile file = VFS.getVirtualFile(context.getRootURL(), "");
-      assertNotNull(file);
-      assertEquals(context.getRoot().getVirtualFile(), file);
-   }
-
-   public void testGetVirtualFileURLChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VirtualFile file1 = VFS.getVirtualFile(context.getRootURL(), "child1");
-      assertNotNull(file1);
-      assertEquals(child1, file1);
-      
-      VirtualFile file2 = VFS.getVirtualFile(context.getRootURL(), "child2");
-      assertNotNull(file2);
-      assertEquals(child2, file2);
-      
-      VirtualFile file3 = VFS.getVirtualFile(context.getRootURL(), "child3");
-      assertNotNull(file3);
-      assertEquals(child3, file3);
-   }
-
-   public void testGetVirtualFileURLNullURL() throws Exception
-   {
-      try
-      {
-         VFS.getVirtualFile((URL) null, "");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLNullPath() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURL(), null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLNoFactory() throws Exception
-   {
-      try
-      {
-         URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
-         VFS.getVirtualFile(url, "");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLIOExceptionGetVFS() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      mockVFSContextFactory.setIOException("getVFSURL");
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURL(), "child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLDoesNotExist() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURL(), "doesnotexist");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetVirtualFileURLIOExceptionFindChild() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChild");
-
-      try
-      {
-         VFS.getVirtualFile(context.getRootURL(), "child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertNotNull(vfs);
-
-      VirtualFile root = vfs.getRoot();
-      assertNotNull(root);
-      
-      assertEquals(context.getRoot().getVirtualFile(), root);
-   }
-
-   public void testGetRootIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.setIOException("getRoot");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertNotNull(vfs);
-
-      try
-      {
-         vfs.getRoot();
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testFindChildRoot() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      
-      assertFindChild(vfs, "", vfs.getRoot());
-   }
-
-   public void testFindChildChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertFindChild(vfs, "child1", child1);
-      assertFindChild(vfs, "child2", child2);
-      assertFindChild(vfs, "child3", child3);
-   }
-
-   public void testFindChildSubChildren() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
-      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
-      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
-      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertFindChild(vfs, "child1", child1);
-      assertFindChild(vfs, "child1/child1,1", child11);
-      assertFindChild(vfs, "child2", child2);
-      assertFindChild(vfs, "child2/child2,1", child21);
-      assertFindChild(vfs, "child2/child2,2", child22);
-      assertFindChild(vfs, "child3", child3);
-      assertFindChild(vfs, "child3/child3,1", child31);
-      assertFindChild(vfs, "child3/child3,2", child32);
-      assertFindChild(vfs, "child3/child3,3", child33);
-   }
-
-   public void testFindChildNullPath() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS vfs = VFS.getVFS(context.getRootURI());
-         vfs.findChild(null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testGetChildNullPath() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      try
-      {
-         VFS vfs = VFS.getVFS(context.getRootURI());
-         vfs.getChild(null);
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testFindChildSimpleDoesNotExist() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.findChild("doesnotexist");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-         assertNull(vfs.getChild("doesnotexist"));
-      }
-   }
-
-   public void testFindChildStructuredDoesNotExist() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.findChild("child1/doesnotexist");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-         assertNull(vfs.getChild("child1/doesnotexist"));
-      }
-   }
-
-   public void testFindChildIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChild");
-
-      try
-      {
-         VFS vfs = VFS.getVFS(context.getRootURI());
-         vfs.findChild("child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetChildIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChild");
-
-      try
-      {
-         VFS vfs = VFS.getVFS(context.getRootURI());
-         vfs.getChild("child1");
-         fail("Should not be here");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren();
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren();
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren();
-      assertNotNull(children);
-      
-      assertEmpty(children);
-   }
-
-   public void testGetAllChildrenIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertChildrenOnLeaf(vfs);
-   }
-
-   public void testGetAllChildrenIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.getChildren();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildrenWithNullFilter() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren(null);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenWithNullFilterStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren(null);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenWithNullFilterNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildren(null);
-      assertNotNull(children);
-      
-      assertEmpty(children);
-   }
-
-   public void testGetAllChildrenWithNullFilterIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertChildrenOnLeaf(vfs, null);
-   }
-
-   public void testGetAllChildrenWithNullFilterIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.getChildren(null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildrenWithFilter() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildren(filter);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testGetAllChildrenWithFilterStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildren(filter);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testGetAllChildrenWithFilterNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildren(filter);
-      assertNotNull(children);
-      
-      assertEmpty(children);
-      assertEmpty(filter.getVisited());
-   }
-
-   public void testGetAllChildrenWithFilterIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      assertChildrenOnLeaf(vfs, filter);
-   }
-
-   public void testGetAllChildrenWithFilterIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      try
-      {
-         vfs.getChildren(filter);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildrenRecursively() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively();
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenRecursivelyStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
-      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
-      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
-      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively();
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child11);
-      expected.add(child2);
-      expected.add(child21);
-      expected.add(child22);
-      expected.add(child3);
-      expected.add(child31);
-      expected.add(child32);
-      expected.add(child33);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenRecursivelyNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively();
-      assertNotNull(children);
-      
-      assertEmpty(children);
-   }
-
-   public void testGetAllChildrenRecursivelyIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertChildrenOnLeafRecursively(vfs);
-   }
-
-   public void testGetAllChildrenRecursivelyIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.getChildrenRecursively();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildrenRecursivelyWithNullFilter() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively(null);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenRecursivelyWithNullFilterStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
-      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
-      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
-      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively(null);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child11);
-      expected.add(child2);
-      expected.add(child21);
-      expected.add(child22);
-      expected.add(child3);
-      expected.add(child31);
-      expected.add(child32);
-      expected.add(child33);
-      
-      assertEquals(expected, children);
-   }
-
-   public void testGetAllChildrenRecursivelyWithNullFilterNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      List<VirtualFile> children = vfs.getChildrenRecursively(null);
-      assertNotNull(children);
-      
-      assertEmpty(children);
-   }
-
-   public void testGetAllChildrenRecursivelyWithNullFilterIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      assertChildrenOnLeafRecursively(vfs, null);
-   }
-
-   public void testGetAllChildrenRecursivelyWithNullFilterIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.getChildrenRecursively(null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testGetAllChildrenRecursivelyWithFilter() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, children);
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testGetAllChildrenRecursivelyWithFilterStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
-      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
-      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
-      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
-      assertNotNull(children);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child11);
-      expected.add(child2);
-      expected.add(child21);
-      expected.add(child22);
-      expected.add(child3);
-      expected.add(child31);
-      expected.add(child32);
-      expected.add(child33);
-      
-      assertEquals(expected, children);
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testGetAllChildrenRecursivelyWithFilterNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
-      assertNotNull(children);
-      
-      assertEmpty(children);
-      assertEmpty(filter.getVisited());
-   }
-
-   public void testGetAllChildrenRecursivelyWithFilterIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      assertChildrenOnLeafRecursively(vfs, filter);
-   }
-
-   public void testGetAllChildrenRecursivelyWithFilterIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      try
-      {
-         vfs.getChildrenRecursively(filter);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-
-   public void testVisitAllChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
-      vfs.visit(visitor);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testVisitAllChildrenStructured() throws Exception
-   {
-      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
-      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
-      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
-      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
-      vfs.visit(visitor);
-      
-      List<VirtualFile> expected = new ArrayList<VirtualFile>();
-      expected.add(child1);
-      expected.add(child2);
-      expected.add(child3);
-      
-      assertEquals(expected, filter.getVisited());
-   }
-
-   public void testVisitAllChildrenNoChildren() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      context.getMockRoot().setLeaf(false);
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
-      vfs.visit(visitor);
-
-      assertEmpty(filter.getVisited());
-   }
-
-   public void testVisitAllChildrenIsLeaf() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
-      vfs.visit(visitor);
-      List<VirtualFile> matched = visitor.getMatched();
-      assertNotNull(matched);
-      assertEmpty(matched);
-   }
-
-   public void testVisitAllChildrenNullVisitor() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      try
-      {
-         vfs.visit(null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testVisitAllChildrenIOException() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContextWithChildren();
-      context.getMockRoot().setIOException("getChildren");
-      
-      VFS vfs = VFS.getVFS(context.getRootURI());
-      MockVirtualFileFilter filter = new MockVirtualFileFilter();
-      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
-      try
-      {
-         vfs.visit(visitor);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IOException.class, t);
-      }
-   }
-   
-   public void testToString() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      VFS vfs = context.getVFS();
-      
-      assertEquals(context.toString(), vfs.toString());
-   }
-   
-   public void testHashCode() throws Exception
-   {
-      MockVFSContext context = registerSimpleVFSContext();
-      VFS vfs = context.getVFS();
-      
-      assertEquals(context.hashCode(), vfs.hashCode());
-   }
-   
-   public void testEquals() throws Exception
-   {
-      MockVFSContext context1 = createSimpleVFSContext();
-      MockVFSContext context2 = createSimpleVFSContext();
-      
-      VFS vfs1 = context1.getVFS();
-      VFS vfs2 = context2.getVFS();
-
-      assertEquals(vfs1, vfs2);
-      
-      MockVFSContext context3 = createSimple2VFSContext();
-      VFS vfs3 = context3.getVFS();
-
-      assertFalse(vfs1.equals(vfs3));
-      assertFalse(vfs2.equals(vfs3));
-
-      assertFalse(vfs1.equals(null));
-
-      assertFalse(vfs1.equals(new Object()));
-   }
-}

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,1384 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.jboss.test.virtual.support.MockURLStreamHandler;
+import org.jboss.test.virtual.support.MockVFSContext;
+import org.jboss.test.virtual.support.MockVirtualFileFilter;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.vfs.helpers.FilterVirtualFileVisitor;
+
+/**
+ * VFSUnitTestCase.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class VFSUnitTestCase extends AbstractMockVFSTest
+{
+   public VFSUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(VFSUnitTestCase.class);
+   }
+
+   public void testVFSOptions() throws Exception
+   {
+      URL url = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(url);
+
+      // currently we don't test any vfs root's behavior
+
+      VFSUtils.enableCopy(vfs);
+      VFSUtils.disableCopy(vfs);
+
+      VFSUtils.enableNoReaper(vfs);
+      VFSUtils.disableNoReaper(vfs);
+
+      VFSUtils.enableCaseSensitive(vfs);
+      VFSUtils.disableCaseSensitive(vfs);
+   }
+
+
+   public void testGetVFSURI() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      MockVFSContext context2 = registerSimple2VFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertNotNull(vfs);
+      assertEquals(context.getVFS(), vfs);
+      
+      VFS vfs2 = VFS.getVFS(context2.getRootURI());
+      assertNotNull(vfs2);
+      assertEquals(context2.getVFS(), vfs2);
+   }
+
+   public void testGetVFSURINull() throws Exception
+   {
+      try
+      {
+         VFS.getVFS((URI) null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVFSURINoFactory() throws Exception
+   {
+      try
+      {
+         URI uri = new URI("doesnotexist:///");
+         VFS.getVFS(uri);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVFSURIIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      mockVFSContextFactory.setIOException("getVFSURI");
+
+      try
+      {
+         VFS.getVFS(context.getRootURI());
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVFSURL() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      MockVFSContext context2 = registerSimple2VFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURL());
+      assertNotNull(vfs);
+      assertEquals(context.getVFS(), vfs);
+      
+      VFS vfs2 = VFS.getVFS(context2.getRootURL());
+      assertNotNull(vfs2);
+      assertEquals(context2.getVFS(), vfs2);
+   }
+
+   public void testGetVFSURLNull() throws Exception
+   {
+      try
+      {
+         VFS.getVFS((URL) null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVFSURLNoFactory() throws Exception
+   {
+      try
+      {
+         URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
+         VFS.getVFS(url);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVFSURLIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      mockVFSContextFactory.setIOException("getVFSURL");
+
+      try
+      {
+         VFS.getVFS(context.getRootURL());
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURI() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      
+      VirtualFile file = VFS.getRoot(context.getRootURI());
+      assertNotNull(file);
+      assertEquals(context.getRoot().getVirtualFile(), file);
+   }
+
+   public void testGetRootURINullURI() throws Exception
+   {
+      try
+      {
+         VFS.getRoot((URI) null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetRootURINoFactory() throws Exception
+   {
+      try
+      {
+         URI uri = new URI("doesnotexist:///");
+         VFS.getRoot(uri);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURIIOExceptionGetVFS() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      mockVFSContextFactory.setIOException("getVFSURI");
+
+      try
+      {
+         VFS.getRoot(context.getRootURI());
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURIIOExceptionGetRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.setIOException("getRoot");
+
+      try
+      {
+         VFS.getRoot(context.getRootURI());
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURIRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      
+      VirtualFile file = VFS.getVirtualFile(context.getRootURI(), "");
+      assertNotNull(file);
+      assertEquals(context.getRoot().getVirtualFile(), file);
+   }
+
+   public void testGetVirtualFileURIChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VirtualFile file1 = VFS.getVirtualFile(context.getRootURI(), "child1");
+      assertNotNull(file1);
+      assertEquals(child1, file1);
+      
+      VirtualFile file2 = VFS.getVirtualFile(context.getRootURI(), "child2");
+      assertNotNull(file2);
+      assertEquals(child2, file2);
+      
+      VirtualFile file3 = VFS.getVirtualFile(context.getRootURI(), "child3");
+      assertNotNull(file3);
+      assertEquals(child3, file3);
+   }
+
+   public void testGetVirtualFileURINullURI() throws Exception
+   {
+      try
+      {
+         VFS.getVirtualFile((URI) null, "");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURINullPath() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURI(), null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURINoFactory() throws Exception
+   {
+      try
+      {
+         URI uri = new URI("doesnotexist:///");
+         VFS.getVirtualFile(uri, "");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURIDoesNotExist() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURI(), "doesnotexist");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURIIOExceptionGetVFS() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      mockVFSContextFactory.setIOException("getVFSURI");
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURI(), "child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURIIOExceptionFindChild() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChild");
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURI(), "child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURL() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      
+      VirtualFile file = VFS.getRoot(context.getRootURL());
+      assertNotNull(file);
+      assertEquals(context.getRoot().getVirtualFile(), file);
+   }
+
+   public void testGetRootURLNullURL() throws Exception
+   {
+      try
+      {
+         VFS.getRoot((URL) null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetRootURLNoFactory() throws Exception
+   {
+      URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
+      try
+      {
+         VFS.getRoot(url);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURLIOExceptionGetVFS() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      mockVFSContextFactory.setIOException("getVFSURL");
+
+      URL url = context.getRootURL();
+      try
+      {
+         VFS.getRoot(url);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRootURLIOExceptionGetRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.setIOException("getRoot");
+
+      URL url = context.getRootURL();
+      try
+      {
+         VFS.getRoot(url);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      
+      VirtualFile file = VFS.getVirtualFile(context.getRootURL(), "");
+      assertNotNull(file);
+      assertEquals(context.getRoot().getVirtualFile(), file);
+   }
+
+   public void testGetVirtualFileURLChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VirtualFile file1 = VFS.getVirtualFile(context.getRootURL(), "child1");
+      assertNotNull(file1);
+      assertEquals(child1, file1);
+      
+      VirtualFile file2 = VFS.getVirtualFile(context.getRootURL(), "child2");
+      assertNotNull(file2);
+      assertEquals(child2, file2);
+      
+      VirtualFile file3 = VFS.getVirtualFile(context.getRootURL(), "child3");
+      assertNotNull(file3);
+      assertEquals(child3, file3);
+   }
+
+   public void testGetVirtualFileURLNullURL() throws Exception
+   {
+      try
+      {
+         VFS.getVirtualFile((URL) null, "");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLNullPath() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURL(), null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLNoFactory() throws Exception
+   {
+      try
+      {
+         URL url = new URL("doesnotexist", "", 0, "", MockURLStreamHandler.INSTANCE);
+         VFS.getVirtualFile(url, "");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLIOExceptionGetVFS() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      mockVFSContextFactory.setIOException("getVFSURL");
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURL(), "child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLDoesNotExist() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURL(), "doesnotexist");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetVirtualFileURLIOExceptionFindChild() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChild");
+
+      try
+      {
+         VFS.getVirtualFile(context.getRootURL(), "child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertNotNull(vfs);
+
+      VirtualFile root = vfs.getRoot();
+      assertNotNull(root);
+      
+      assertEquals(context.getRoot().getVirtualFile(), root);
+   }
+
+   public void testGetRootIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.setIOException("getRoot");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertNotNull(vfs);
+
+      try
+      {
+         vfs.getRoot();
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testFindChildRoot() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      
+      assertFindChild(vfs, "", vfs.getRoot());
+   }
+
+   public void testFindChildChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertFindChild(vfs, "child1", child1);
+      assertFindChild(vfs, "child2", child2);
+      assertFindChild(vfs, "child3", child3);
+   }
+
+   public void testFindChildSubChildren() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
+      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
+      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
+      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertFindChild(vfs, "child1", child1);
+      assertFindChild(vfs, "child1/child1,1", child11);
+      assertFindChild(vfs, "child2", child2);
+      assertFindChild(vfs, "child2/child2,1", child21);
+      assertFindChild(vfs, "child2/child2,2", child22);
+      assertFindChild(vfs, "child3", child3);
+      assertFindChild(vfs, "child3/child3,1", child31);
+      assertFindChild(vfs, "child3/child3,2", child32);
+      assertFindChild(vfs, "child3/child3,3", child33);
+   }
+
+   public void testFindChildNullPath() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS vfs = VFS.getVFS(context.getRootURI());
+         vfs.findChild(null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testGetChildNullPath() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      try
+      {
+         VFS vfs = VFS.getVFS(context.getRootURI());
+         vfs.getChild(null);
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testFindChildSimpleDoesNotExist() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.findChild("doesnotexist");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+         assertNull(vfs.getChild("doesnotexist"));
+      }
+   }
+
+   public void testFindChildStructuredDoesNotExist() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.findChild("child1/doesnotexist");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+         assertNull(vfs.getChild("child1/doesnotexist"));
+      }
+   }
+
+   public void testFindChildIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChild");
+
+      try
+      {
+         VFS vfs = VFS.getVFS(context.getRootURI());
+         vfs.findChild("child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetChildIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChild");
+
+      try
+      {
+         VFS vfs = VFS.getVFS(context.getRootURI());
+         vfs.getChild("child1");
+         fail("Should not be here");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren();
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren();
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren();
+      assertNotNull(children);
+      
+      assertEmpty(children);
+   }
+
+   public void testGetAllChildrenIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertChildrenOnLeaf(vfs);
+   }
+
+   public void testGetAllChildrenIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.getChildren();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildrenWithNullFilter() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren(null);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenWithNullFilterStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren(null);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenWithNullFilterNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildren(null);
+      assertNotNull(children);
+      
+      assertEmpty(children);
+   }
+
+   public void testGetAllChildrenWithNullFilterIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertChildrenOnLeaf(vfs, null);
+   }
+
+   public void testGetAllChildrenWithNullFilterIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.getChildren(null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildrenWithFilter() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildren(filter);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testGetAllChildrenWithFilterStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildren(filter);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testGetAllChildrenWithFilterNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildren(filter);
+      assertNotNull(children);
+      
+      assertEmpty(children);
+      assertEmpty(filter.getVisited());
+   }
+
+   public void testGetAllChildrenWithFilterIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      assertChildrenOnLeaf(vfs, filter);
+   }
+
+   public void testGetAllChildrenWithFilterIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      try
+      {
+         vfs.getChildren(filter);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildrenRecursively() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively();
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenRecursivelyStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
+      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
+      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
+      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively();
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child11);
+      expected.add(child2);
+      expected.add(child21);
+      expected.add(child22);
+      expected.add(child3);
+      expected.add(child31);
+      expected.add(child32);
+      expected.add(child33);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenRecursivelyNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively();
+      assertNotNull(children);
+      
+      assertEmpty(children);
+   }
+
+   public void testGetAllChildrenRecursivelyIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertChildrenOnLeafRecursively(vfs);
+   }
+
+   public void testGetAllChildrenRecursivelyIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.getChildrenRecursively();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildrenRecursivelyWithNullFilter() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively(null);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenRecursivelyWithNullFilterStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
+      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
+      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
+      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively(null);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child11);
+      expected.add(child2);
+      expected.add(child21);
+      expected.add(child22);
+      expected.add(child3);
+      expected.add(child31);
+      expected.add(child32);
+      expected.add(child33);
+      
+      assertEquals(expected, children);
+   }
+
+   public void testGetAllChildrenRecursivelyWithNullFilterNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      List<VirtualFile> children = vfs.getChildrenRecursively(null);
+      assertNotNull(children);
+      
+      assertEmpty(children);
+   }
+
+   public void testGetAllChildrenRecursivelyWithNullFilterIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      assertChildrenOnLeafRecursively(vfs, null);
+   }
+
+   public void testGetAllChildrenRecursivelyWithNullFilterIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.getChildrenRecursively(null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testGetAllChildrenRecursivelyWithFilter() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, children);
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testGetAllChildrenRecursivelyWithFilterStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child11 = getChildHandler(context, "child1/child1,1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child21 = getChildHandler(context, "child2/child2,1").getVirtualFile();
+      VirtualFile child22 = getChildHandler(context, "child2/child2,2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      VirtualFile child31 = getChildHandler(context, "child3/child3,1").getVirtualFile();
+      VirtualFile child32 = getChildHandler(context, "child3/child3,2").getVirtualFile();
+      VirtualFile child33 = getChildHandler(context, "child3/child3,3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
+      assertNotNull(children);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child11);
+      expected.add(child2);
+      expected.add(child21);
+      expected.add(child22);
+      expected.add(child3);
+      expected.add(child31);
+      expected.add(child32);
+      expected.add(child33);
+      
+      assertEquals(expected, children);
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testGetAllChildrenRecursivelyWithFilterNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      List<VirtualFile> children = vfs.getChildrenRecursively(filter);
+      assertNotNull(children);
+      
+      assertEmpty(children);
+      assertEmpty(filter.getVisited());
+   }
+
+   public void testGetAllChildrenRecursivelyWithFilterIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      assertChildrenOnLeafRecursively(vfs, filter);
+   }
+
+   public void testGetAllChildrenRecursivelyWithFilterIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      try
+      {
+         vfs.getChildrenRecursively(filter);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+
+   public void testVisitAllChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
+      vfs.visit(visitor);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testVisitAllChildrenStructured() throws Exception
+   {
+      MockVFSContext context = registerStructuredVFSContextWithSubChildren();
+      VirtualFile child1 = getChildHandler(context, "child1").getVirtualFile();
+      VirtualFile child2 = getChildHandler(context, "child2").getVirtualFile();
+      VirtualFile child3 = getChildHandler(context, "child3").getVirtualFile();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
+      vfs.visit(visitor);
+      
+      List<VirtualFile> expected = new ArrayList<VirtualFile>();
+      expected.add(child1);
+      expected.add(child2);
+      expected.add(child3);
+      
+      assertEquals(expected, filter.getVisited());
+   }
+
+   public void testVisitAllChildrenNoChildren() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      context.getMockRoot().setLeaf(false);
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
+      vfs.visit(visitor);
+
+      assertEmpty(filter.getVisited());
+   }
+
+   public void testVisitAllChildrenIsLeaf() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
+      vfs.visit(visitor);
+      List<VirtualFile> matched = visitor.getMatched();
+      assertNotNull(matched);
+      assertEmpty(matched);
+   }
+
+   public void testVisitAllChildrenNullVisitor() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      try
+      {
+         vfs.visit(null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testVisitAllChildrenIOException() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContextWithChildren();
+      context.getMockRoot().setIOException("getChildren");
+      
+      VFS vfs = VFS.getVFS(context.getRootURI());
+      MockVirtualFileFilter filter = new MockVirtualFileFilter();
+      FilterVirtualFileVisitor visitor = new FilterVirtualFileVisitor(filter);
+      try
+      {
+         vfs.visit(visitor);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IOException.class, t);
+      }
+   }
+   
+   public void testToString() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      VFS vfs = context.getVFS();
+      
+      assertEquals(context.toString(), vfs.toString());
+   }
+   
+   public void testHashCode() throws Exception
+   {
+      MockVFSContext context = registerSimpleVFSContext();
+      VFS vfs = context.getVFS();
+      
+      assertEquals(context.hashCode(), vfs.hashCode());
+   }
+   
+   public void testEquals() throws Exception
+   {
+      MockVFSContext context1 = createSimpleVFSContext();
+      MockVFSContext context2 = createSimpleVFSContext();
+      
+      VFS vfs1 = context1.getVFS();
+      VFS vfs2 = context2.getVFS();
+
+      assertEquals(vfs1, vfs2);
+      
+      MockVFSContext context3 = createSimple2VFSContext();
+      VFS vfs3 = context3.getVFS();
+
+      assertFalse(vfs1.equals(vfs3));
+      assertFalse(vfs2.equals(vfs3));
+
+      assertFalse(vfs1.equals(null));
+
+      assertFalse(vfs1.equals(new Object()));
+   }
+}

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,61 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.net.URL;
-import java.util.List;
-import java.util.ArrayList;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.VFSUtils;
-
-/**
- * VFSUtilTestCase.
- *
- * @author <a href="ales.justin at jboss.com">Ales Justin</a>
- */
-public class VFSUtilTestCase extends AbstractMockVFSTest
-{
-   public VFSUtilTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(VFSUtilTestCase.class);
-   }
-
-   public void testAddManifestLocations() throws Throwable
-   {
-      URL url = getResource("/vfs/test");
-      VirtualFile root = VFS.getRoot(url);
-      VirtualFile file = root.getChild("badmf.jar");
-      assertNotNull(file);
-      List<VirtualFile> paths = new ArrayList<VirtualFile>();
-      VFSUtils.addManifestLocations(file, paths);
-      assertEquals(3, paths.size());
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,120 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+
+/**
+ * VFSUtilTestCase.
+ *
+ * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @author anil.saldhana at jboss.com
+ */
+public class VFSUtilTestCase extends AbstractMockVFSTest
+{
+   public VFSUtilTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(VFSUtilTestCase.class);
+   }
+
+   public void testAddManifestLocations() throws Throwable
+   {
+      URL url = getResource("/vfs/test");
+      VirtualFile root = VFS.getRoot(url);
+      VirtualFile file = root.getChild("badmf.jar");
+      assertNotNull(file);
+      List<VirtualFile> paths = new ArrayList<VirtualFile>();
+      VFSUtils.addManifestLocations(file, paths);
+      assertEquals(3, paths.size());
+   }
+
+   public void testOptionsPropagation() throws Exception
+   {
+      URL url = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(url);
+      VFSUtils.enableNoReaper(vfs);
+      VirtualFile root = vfs.getRoot();
+      assertOption(root, "nested", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar/META-INF", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar/META-INF/empty.txt", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar/complex.jar", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar/complex.jar/subfolder", VFSUtils.NO_REAPER_QUERY);
+      assertOption(root, "nested/nested.jar/complex.jar/subfolder/subchild", VFSUtils.NO_REAPER_QUERY);
+
+      VirtualFile subchild = root.findChild("nested/nested.jar/complex.jar/subfolder/subchild");
+      VFSUtils.disableNoReaper(subchild);
+      assertNull(VFSUtils.getOption(subchild, VFSUtils.NO_REAPER_QUERY));
+   }
+
+   protected void assertOption(VirtualFile root, String path, String optionKey) throws Exception
+   {
+      VirtualFile child = root.findChild(path);
+      String optionValue = VFSUtils.getOption(root, optionKey);
+      assertNotNull(optionValue);
+      assertEquals(optionValue, VFSUtils.getOption(child, optionKey));
+   }
+
+   public void testRealURL() throws Exception
+   {
+	   //Regular jar
+	   URL url = getResource("/vfs/test");
+	   VirtualFile root = VFS.getRoot(url);
+	   VirtualFile jarFile = root.getChild("badmf.jar");
+	      
+	   URL vfsURL = jarFile.toURL(); 
+	   assertTrue(vfsURL.toExternalForm().startsWith("vfszip"));
+	   URL realURL = VFSUtils.getRealURL(jarFile);
+      // TODO - JBVFS-77 --> do proper tests!
+	   assertTrue(realURL.toExternalForm().startsWith("jar:"));
+	   
+	   //Nested file in a jar
+	   url = getResource("/vfs/test/nested");
+	   root = VFS.getRoot(url);
+	   VirtualFile nestedFile = root.getChild("/nested.jar/META-INF/empty.txt");
+	   realURL = VFSUtils.getRealURL(nestedFile);
+      // TODO - JBVFS-77 --> do proper tests!
+	   assertTrue(realURL.toExternalForm().startsWith("jar:"));
+	     
+	   //Regular file
+	   url = getResource("/vfs/context/file/simple");
+	   VirtualFile regularFile = VFS.getRoot(url).getChild("tomodify");
+	   vfsURL = regularFile.toURL();
+	   assertTrue(vfsURL.getProtocol().startsWith("vfsfile"));
+	   realURL = VFSUtils.getRealURL(regularFile);
+      // TODO - JBVFS-77 --> do proper tests!
+	   assertTrue(realURL.toExternalForm().startsWith("file:"));
+   }
+}
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	2008-11-07 10:57:33 UTC (rev 80637)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -1,177 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, JBoss Inc., and individual contributors as indicated
-* by the @authors tag. See the copyright.txt in the distribution for a
-* full listing of individual contributors.
-*
-* This is free software; you can redistribute it and/or modify it
-* under the terms of the GNU Lesser General Public License as
-* published by the Free Software Foundation; either version 2.1 of
-* the License, or (at your option) any later version.
-*
-* This software is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this software; if not, write to the Free
-* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
-* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-*/
-package org.jboss.test.virtual.test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-
-import junit.framework.Test;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.plugins.context.jar.JarUtils;
-import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * ZipEntryVFSContextUnitTestCase.
- *
- * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
- * @version $Revision: 1.0 $
- */
-public class ZipEntryVFSContextUnitTestCase extends JARVFSContextUnitTestCase
-{
-   public ZipEntryVFSContextUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      VFS.init();
-      System.out.println("java.protocol.handler.pkgs: " + System.getProperty("java.protocol.handler.pkgs"));
-      return suite(ZipEntryVFSContextUnitTestCase.class);
-   }
-
-   protected VFSContext getVFSContext(String name) throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/" + name + ".jar");
-      url = JarUtils.createJarURL(url);
-      return new ZipEntryContext(url);
-   }
-
-   protected VFSContext createVSFContext(URL url) throws Exception
-   {
-      return new ZipEntryContext(url);
-   }
-
-   /**
-    * Test detection of underlying jar file removal through exists()
-    *
-    * @throws Exception for any error
-    */
-   public void testRootExists() throws Exception
-   {
-      URL url = getResource("/vfs/test/outer.jar");
-      File tmpJar = File.createTempFile("vfstest", ".jar");
-
-      InputStream is = url.openStream();
-      OutputStream os = new FileOutputStream(tmpJar);
-      VFSUtils.copyStreamAndClose(is, os);
-
-      ZipEntryContext context = new ZipEntryContext(tmpJar.toURL());
-      assertTrue("context.getRoot().exists()", context.getRoot().exists());
-
-      boolean isDeleted = context.getRoot().delete(1000);
-      assertTrue("delete tmp file: " + tmpJar, isDeleted);
-      assertFalse("context.getRoot().exists()", context.getRoot().exists());
-   }
-
-   /**
-    * Test for proper handling when file appears to be an archive but
-    * trying to handle it produces an exception. Proper behaviour
-    * is to ignore exception and treat the file as non-archive.
-    *
-    * @throws Exception for any error
-    */
-   public void testNotAnArchive() throws Exception
-   {
-      URL url = getResource("/vfs/context/jar/");
-      FileSystemContext ctx = new FileSystemContext(url);
-
-      // we just do basic sanity checks
-
-      // valid archive
-
-      VirtualFileHandler handler = ctx.getRoot().getChild("archive.jar");
-      //assertTrue("is vfszip", "vfszip".equals(handler.toURL().getProtocol()));
-      assertFalse("is leaf", handler.isLeaf());
-      assertTrue("exists", handler.exists());
-      assertNotNull("pathName not null", handler.getPathName());
-      assertNotNull("name not null", handler.getName());
-      assertNotNull("parent not null", handler.getParent());
-      assertTrue("lastModified > 0", handler.getLastModified() > 0);
-      assertTrue("size > 0", handler.getSize() > 0);
-      assertNotNull("VF not null", handler.getVirtualFile());
-      assertFalse("hasBeenModified == false", handler.hasBeenModified());
-      assertFalse("hidden == false", handler.isHidden());
-      assertFalse("nested == false", handler.isNested());
-      assertNotNull("toURI not null", handler.toURI());
-      assertNotNull("toURL not null", handler.toURL());
-      assertNotNull("toVfsUrl not null", handler.toVfsUrl());
-
-      ByteArrayOutputStream memOut = new ByteArrayOutputStream();
-      VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
-      assertTrue("read archive content", memOut.size() == handler.getSize());
-
-      // invalid archive
-
-      handler = ctx.getRoot().getChild("notanarchive.jar");
-      //assertTrue("is leaf", handler.isLeaf());
-      assertTrue("exists", handler.exists());
-      assertTrue("lastModified > 0", handler.getLastModified() > 0);
-      assertNotNull("pathName not null", handler.getPathName());
-      assertNotNull("name not null", handler.getName());
-      assertNotNull("parent not null", handler.getParent());
-      assertTrue("size > 0", handler.getSize() > 0);
-      assertNotNull("VF not null", handler.getVirtualFile());
-      assertFalse("hasBeenModified == false", handler.hasBeenModified());
-      assertFalse("hidden == false", handler.isHidden());
-      assertFalse("nested == false", handler.isNested());
-      assertNotNull("toURI not null", handler.toURI());
-      assertNotNull("toURL not null", handler.toURL());
-      assertNotNull("toVfsUrl not null", handler.toVfsUrl());
-
-      memOut = new ByteArrayOutputStream();
-      VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
-      assertTrue("read archive content", memOut.size() == handler.getSize());
-   }
-
-   /**
-    * Handler representing a directory must return a recomposed zip archive
-    * that has requested entry as its root.
-    *
-    * This behavior is new to vfszip. vfsjar returns an empty stream.
-    *
-    * @throws Exception for any error
-    */
-   public void testDirectoryZipEntryOpenStream() throws Exception
-   {
-      doDirectoryZipEntryOpenStream(false);
-   }
-
-   // we need to make sure this doesn't get touched before
-   protected String getNestedName()
-   {
-      return super.getNestedName() + "_copy";
-   }
-
-   protected String getProtocol()
-   {
-      return "vfszip";
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.GA/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	2008-11-24 09:55:49 UTC (rev 81475)
@@ -0,0 +1,254 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * ZipEntryVFSContextUnitTestCase.
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+public class ZipEntryVFSContextUnitTestCase extends JARVFSContextUnitTestCase
+{
+   public ZipEntryVFSContextUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      VFS.init();
+      System.out.println("java.protocol.handler.pkgs: " + System.getProperty("java.protocol.handler.pkgs"));
+      return suite(ZipEntryVFSContextUnitTestCase.class);
+   }
+
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/" + name + ".jar");
+      url = JarUtils.createJarURL(url);
+      return new ZipEntryContext(url);
+   }
+
+   protected VFSContext createVSFContext(URL url) throws Exception
+   {
+      return new ZipEntryContext(url);
+   }
+
+   /**
+    * Test detection of underlying jar file removal through exists()
+    *
+    * @throws Exception for any error
+    */
+   public void testRootExists() throws Exception
+   {
+      URL url = getResource("/vfs/test/outer.jar");
+      File tmpJar = File.createTempFile("vfstest", ".jar");
+
+      InputStream is = url.openStream();
+      OutputStream os = new FileOutputStream(tmpJar);
+      VFSUtils.copyStreamAndClose(is, os);
+
+      ZipEntryContext context = new ZipEntryContext(tmpJar.toURL());
+      assertTrue("context.getRoot().exists()", context.getRoot().exists());
+
+      boolean isDeleted = context.getRoot().delete(1000);
+      assertTrue("delete tmp file: " + tmpJar, isDeleted);
+      assertFalse("context.getRoot().exists()", context.getRoot().exists());
+   }
+
+   /**
+    * Test for proper handling when file appears to be an archive but
+    * trying to handle it produces an exception. Proper behaviour
+    * is to ignore exception and treat the file as non-archive.
+    *
+    * @throws Exception for any error
+    */
+   public void testNotAnArchive() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/");
+      FileSystemContext ctx = new FileSystemContext(url);
+
+      // we just do basic sanity checks
+
+      // valid archive
+
+      VirtualFileHandler handler = ctx.getRoot().getChild("archive.jar");
+      //assertTrue("is vfszip", "vfszip".equals(handler.toURL().getProtocol()));
+      assertFalse("is leaf", handler.isLeaf());
+      assertTrue("exists", handler.exists());
+      assertNotNull("pathName not null", handler.getPathName());
+      assertNotNull("name not null", handler.getName());
+      assertNotNull("parent not null", handler.getParent());
+      assertTrue("lastModified > 0", handler.getLastModified() > 0);
+      assertTrue("size > 0", handler.getSize() > 0);
+      assertNotNull("VF not null", handler.getVirtualFile());
+      assertFalse("hasBeenModified == false", handler.hasBeenModified());
+      assertFalse("hidden == false", handler.isHidden());
+      assertFalse("nested == false", handler.isNested());
+      assertNotNull("toURI not null", handler.toURI());
+      assertNotNull("toURL not null", handler.toURL());
+      assertNotNull("toVfsUrl not null", handler.toVfsUrl());
+
+      ByteArrayOutputStream memOut = new ByteArrayOutputStream();
+      VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
+      assertTrue("read archive content", memOut.size() == handler.getSize());
+
+      // invalid archive
+
+      handler = ctx.getRoot().getChild("notanarchive.jar");
+      //assertTrue("is leaf", handler.isLeaf());
+      assertTrue("exists", handler.exists());
+      assertTrue("lastModified > 0", handler.getLastModified() > 0);
+      assertNotNull("pathName not null", handler.getPathName());
+      assertNotNull("name not null", handler.getName());
+      assertNotNull("parent not null", handler.getParent());
+      assertTrue("size > 0", handler.getSize() > 0);
+      assertNotNull("VF not null", handler.getVirtualFile());
+      assertFalse("hasBeenModified == false", handler.hasBeenModified());
+      assertFalse("hidden == false", handler.isHidden());
+      assertFalse("nested == false", handler.isNested());
+      assertNotNull("toURI not null", handler.toURI());
+      assertNotNull("toURL not null", handler.toURL());
+      assertNotNull("toVfsUrl not null", handler.toVfsUrl());
+
+      memOut = new ByteArrayOutputStream();
+      VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
+      assertTrue("read archive content", memOut.size() == handler.getSize());
+   }
+
+   /**
+    * Real URL test
+    *
+    * @throws Exception for any error
+    */
+   public void testCustomRealURL() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/");
+      FileSystemContext ctx = new FileSystemContext(url);
+
+      // valid archive
+      VirtualFileHandler root = ctx.getRoot();
+      assertEquals("Context Real URL", url.toExternalForm(), root.getRealURL().toExternalForm());
+      String jarName = "archive.jar";
+      VirtualFileHandler archive = root.getChild(jarName);
+      assertEquals("Child Real URL", "jar:" + url.toExternalForm() + jarName + "!/", archive.getRealURL().toExternalForm());
+
+      url = getResource("/vfs/test/");
+      ctx = new FileSystemContext(url);
+      root = ctx.getRoot();
+
+      jarName = "level1.zip";
+      archive = root.getChild(jarName);
+      String nestedName = "level2.zip";
+      VirtualFileHandler nested = archive.getChild(nestedName);
+
+      String jarURL = "jar:" + url.toExternalForm() + jarName + "!/" + nestedName;
+      assertEquals("First level nested Real URL", jarURL, nested.getRealURL().toExternalForm());
+
+      nested = nested.getChild("level3.zip");
+      assertEquals("Second level nested Real URL", jarURL, nested.getRealURL().toExternalForm());
+
+      // nested root test
+      url = getResource("/vfs/test/");
+      ZipEntryContext zctx = new ZipEntryContext(new URL("vfszip:" + url.getPath() + "/level1.zip/level2.zip/level3.zip"));
+
+      VirtualFileHandler handler = zctx.getRoot();
+      assertEquals("Nested root Real URL", jarURL, handler.getRealURL().toExternalForm());
+
+      List<VirtualFileHandler> children = handler.getChildren(false);
+      for (VirtualFileHandler child: children)
+      {
+         assertEquals("Nested root Real URL", jarURL, child.getRealURL().toExternalForm());
+      }
+   }
+
+   /**
+    * Test that options are properly propagated to mounted subcontexts
+    *
+    * @throws IOException
+    */
+   public void testOptionPropagation() throws IOException
+   {
+      // jar:file: url test
+      URL url = getResource("/vfs/test/level1.zip");
+      VFS vfs = VFS.getVFS(new URL("jar:file:" + url.getPath() + "!/"));
+      VFSUtils.enableNoReaper(vfs);
+
+      VirtualFile vf = vfs.getChild("level2.zip/level3.zip");
+      assertEquals("jar:file: option propagation", VFSUtils.getOption(vf, VFSUtils.NO_REAPER_QUERY), "true");
+
+      // vfszip: url test
+      vfs = VFS.getVFS(new URL("vfszip:" + url.getPath()));
+      VFSUtils.enableNoReaper(vfs);
+
+      vf = vfs.getChild("level2.zip/level3.zip");
+      assertEquals("vfszip: option propagation", VFSUtils.getOption(vf, VFSUtils.NO_REAPER_QUERY), "true");
+   }
+
+   /**
+    * Handler representing a directory must return a recomposed zip archive
+    * that has requested entry as its root.
+    *
+    * This behavior is new to vfszip. vfsjar returns an empty stream.
+    *
+    * @throws Exception for any error
+    */
+   public void testDirectoryZipEntryOpenStream() throws Exception
+   {
+      doDirectoryZipEntryOpenStream(false);
+   }
+
+   // we need to make sure this doesn't get touched before
+   protected String getNestedName()
+   {
+      return super.getNestedName() + "_copy";
+   }
+
+   protected String getProtocol()
+   {
+      return "vfszip";
+   }
+
+   protected boolean isRealURLSupported()
+   {
+      return true;
+   }
+}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.GA/src/test/resources/vfs/context/file/nested (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/resources/vfs/context/file/nested)

Copied: projects/vfs/tags/2.0.0.GA/src/test/resources/vfs/test/zipeinit.jar (from rev 81472, projects/vfs/branches/Branch_2_0/src/test/resources/vfs/test/zipeinit.jar)
===================================================================
(Binary files differ)




More information about the jboss-cvs-commits mailing list