[jboss-cvs] JBossAS SVN: r74090 - in projects/vfs/tags: 2.0.0.Beta13 and 10 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Jun 4 08:18:45 EDT 2008


Author: alesj
Date: 2008-06-04 08:18:45 -0400 (Wed, 04 Jun 2008)
New Revision: 74090

Added:
   projects/vfs/tags/2.0.0.Beta13/
   projects/vfs/tags/2.0.0.Beta13/pom.xml
   projects/vfs/tags/2.0.0.Beta13/release-pom.xml
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java
Removed:
   projects/vfs/tags/2.0.0.Beta13/pom.xml
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java
   projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java
Log:
[maven-release-plugin]  copy for tag 2.0.0.Beta13

Copied: projects/vfs/tags/2.0.0.Beta13 (from rev 74078, projects/vfs/trunk)

Deleted: projects/vfs/tags/2.0.0.Beta13/pom.xml
===================================================================
--- projects/vfs/trunk/pom.xml	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/pom.xml	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,121 +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-beta-2</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/trunk</connection>    
-    <developerConnection>scm:svn:https://svn.jboss.org/repos/jbossas/projects/vfs/trunk</developerConnection>
-    <url>https://svn.jboss.org/repos/jbossas/projects/vfs/trunk</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.5.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>
-        </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.Beta13/pom.xml (from rev 74089, projects/vfs/trunk/pom.xml)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/pom.xml	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/pom.xml	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,121 @@
+<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-beta-2</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.jboss</groupId>
+  <artifactId>jboss-vfs</artifactId>
+  <packaging>jar</packaging>
+  <version>2.0.0.Beta13</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.Beta13</connection>    
+    <developerConnection>scm:svn:https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.Beta13</developerConnection>
+    <url>https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.Beta13</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.5.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>
+        </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.Beta13/release-pom.xml (from rev 74089, projects/vfs/trunk/release-pom.xml)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/release-pom.xml	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/release-pom.xml	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8"?><project>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.jboss</groupId>
+  <artifactId>jboss-vfs</artifactId>
+  <name>JBoss VFS</name>
+  <version>2.0.0.Beta13</version>
+  <description>A VFS library</description>
+  <url>http://www.jboss.org</url>
+  <issueManagement>
+    <system>jira</system>
+    <url>http://jira.jboss.com/</url>
+  </issueManagement>
+  <licenses>
+    <license>
+      <name>lgpl</name>
+      <url>http://repository.jboss.org/licenses/lgpl.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <connection>https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.Beta13</connection>
+    <developerConnection>https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.Beta13</developerConnection>
+    <url>https://svn.jboss.org/repos/jbossas/projects/vfs/tags/2.0.0.Beta13</url>
+  </scm>
+  <organization>
+    <name>JBoss, A division of Red Hat, Inc</name>
+    <url>http://www.jboss.org</url>
+  </organization>
+  <build>
+    <sourceDirectory>src/main/java</sourceDirectory>
+    <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
+    <testSourceDirectory>src/test/java</testSourceDirectory>
+    <outputDirectory>target/classes</outputDirectory>
+    <testOutputDirectory>target/test-classes</testOutputDirectory>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+      </resource>
+    </resources>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+      </testResource>
+    </testResources>
+    <directory>target</directory>
+    <finalName>jboss-vfs</finalName>
+    <plugins>
+      <plugin>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.0</version>
+        <configuration>
+          <debug>true</debug>
+          <source>1.5</source>
+          <target>1.5</target>
+          <showDeprecation>true</showDeprecation>
+          <showWarnings>true</showWarnings>
+          <optimize>true</optimize>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-source-plugin</artifactId>
+        <version>2.0.3</version>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+          <execution>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+        <inherited>true</inherited>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>2.3.1</version>
+        <configuration>
+          <forkMode>always</forkMode>
+          <useSystemClassLoader>true</useSystemClassLoader>
+          <redirectTestOutputToFile>true</redirectTestOutputToFile>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-release-plugin</artifactId>
+        <version>2.0-beta-7</version>
+        <configuration>
+          <tagBase>https://svn.jboss.org/repos/jbossas/projects/vfs/tags</tagBase>
+          <generateReleasePoms>true</generateReleasePoms>
+          <useReleaseProfile>false</useReleaseProfile>
+          <arguments>-Prelease</arguments>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <repositories>
+    <repository>
+      <snapshots />
+      <id>snapshots.jboss.org</id>
+      <url>http://snapshots.jboss.org/maven2</url>
+    </repository>
+    <repository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>repository.jboss.org</id>
+      <url>http://repository.jboss.org/maven2</url>
+    </repository>
+    <repository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>central</id>
+      <name>Maven Repository Switchboard</name>
+      <url>http://repo1.maven.org/maven2</url>
+    </repository>
+  </repositories>
+  <pluginRepositories>
+    <pluginRepository>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>repository.jboss.org</id>
+      <url>http://repository.jboss.org/maven2</url>
+    </pluginRepository>
+    <pluginRepository>
+      <snapshots />
+      <id>snapshots.jboss.org</id>
+      <url>http://snapshots.jboss.org/maven2</url>
+    </pluginRepository>
+    <pluginRepository>
+      <releases>
+        <updatePolicy>never</updatePolicy>
+      </releases>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+      <id>central</id>
+      <name>Maven Plugin Repository</name>
+      <url>http://repo1.maven.org/maven2</url>
+    </pluginRepository>
+  </pluginRepositories>
+  <dependencies>
+    <dependency>
+      <groupId>apache-log4j</groupId>
+      <artifactId>log4j</artifactId>
+      <version>1.2.14</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>jboss.profiler.jvmti</groupId>
+      <artifactId>jboss-profiler-jvmti</artifactId>
+      <version>1.0.0.CR5</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.4</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.7.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant-junit</artifactId>
+      <version>1.7.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.ant</groupId>
+      <artifactId>ant-launcher</artifactId>
+      <version>1.7.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss</groupId>
+      <artifactId>jboss-common-core</artifactId>
+      <version>2.2.5.GA</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.jbossas</groupId>
+      <artifactId>jboss-server-manager</artifactId>
+      <version>0.1.0.GA</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.logging</groupId>
+      <artifactId>jboss-logging-log4j</artifactId>
+      <version>2.0.5.GA</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.logging</groupId>
+      <artifactId>jboss-logging-spi</artifactId>
+      <version>2.0.5.GA</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.test</groupId>
+      <artifactId>jboss-test</artifactId>
+      <version>1.1.0.GA</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <reporting>
+    <outputDirectory>target/site</outputDirectory>
+    <plugins>
+      <plugin>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.2</version>
+        <configuration>
+          <links>
+            <link>http://java.sun.com/j2se/1.5.0/docs/api</link>
+          </links>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.0.1</version>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-report-plugin</artifactId>
+        <version>2.3</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>report-only</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>taglist-maven-plugin</artifactId>
+        <version>2.0</version>
+      </plugin>
+    </plugins>
+  </reporting>
+  <distributionManagement>
+    <repository>
+      <id>repository.jboss.org</id>
+      <url>file:///projects/repository/maven2</url>
+    </repository>
+    <snapshotRepository>
+      <id>snapshots.jboss.org</id>
+      <name>JBoss Snapshot Repository</name>
+      <url>dav:https://snapshots.jboss.org/maven2</url>
+    </snapshotRepository>
+  </distributionManagement>
+  <properties>
+    <maven.repository.root>/projects/repository/maven2</maven.repository.root>
+    <version.junit>4.4</version.junit>
+    <jboss.repository.root>/projects/repository/jboss</jboss.repository.root>
+    <version.jboss.logging>2.0.5.GA</version.jboss.logging>
+    <version.jboss.test>1.1.0.GA</version.jboss.test>
+    <version.jboss.common.core>2.2.5.GA</version.jboss.common.core>
+  </properties>
+</project>
\ No newline at end of file

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,620 +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.File;
-import java.io.FileOutputStream;
-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.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-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.id.GUID;
-import org.jboss.virtual.plugins.context.DelegatingHandler;
-import org.jboss.virtual.plugins.context.file.FileSystemContext;
-import org.jboss.virtual.plugins.context.jar.AbstractJarHandler;
-import org.jboss.virtual.plugins.context.jar.NestedJarHandler;
-import org.jboss.virtual.plugins.context.zip.ZipEntryHandler;
-import org.jboss.virtual.spi.LinkInfo;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * VFS Utilities
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class VFSUtils
-{
-   /** The log */
-   private static final Logger log = Logger.getLogger(VFSUtils.class);
-   /** The link */
-   public static final String VFS_LINK_PREFIX = ".vfslink";
-   /** 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";
-
-   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")));
-      }
-   }
-
-   public synchronized static File getTempDirectory()
-   {
-      if (tempDir == null)
-      {
-         tempDir = AccessController.doPrivileged(new GetTempDir());
-         log.info("VFS temp dir: " + tempDir);
-      }
-      return tempDir;
-   }
-
-   /**
-    * 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)
-   {
-      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)
-         throw new IllegalStateException(file + " has no parent.");
-
-      URL parentURL;
-      URL vfsRootURL;
-      int rootPathLength;
-      try
-      {
-         parentURL = parent.toURL();
-         vfsRootURL = file.getVFS().getRoot().toURL();
-         rootPathLength = vfsRootURL.getPath().length();
-      }
-      catch(URISyntaxException e)
-      {
-         IOException ioe = new IOException("Failed to get parent URL for " + file);
-         ioe.initCause(e);
-         throw ioe;
-      }
-
-      StringTokenizer tokenizer = new StringTokenizer(classPath);
-      while (tokenizer.hasMoreTokens())
-      {
-         String path = tokenizer.nextToken();
-         try
-         {
-            String parentPath = parentURL.toString();
-            if(parentPath.endsWith("/") == false)
-               parentPath += "/";
-            URL libURL = new URL(parentPath + path);
-            String libPath = libURL.getPath();
-            // TODO, this occurs for inner jars. Doubtful that such a mf cp is valid
-            if( rootPathLength > libPath.length() )
-               throw new IOException("Invalid rootPath: "+vfsRootURL+", libPath: "+libPath);
-
-            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;
-      try
-      {
-         manifest = archive.findChild(JarFile.MANIFEST_NAME);
-      }
-      catch (IOException ignored)
-      {
-         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
-   {
-      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
-    {
-       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;
-   }
-
-   /**
-    * Get the name.
-    *
-    * @param uri the uri
-    * @return name from uri's path
-    */
-   public static String getName(URI 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 = new HashMap<String, String>();
-      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)
-   {
-      return name.indexOf(VFS_LINK_PREFIX) >= 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
-   {
-      List<LinkInfo> info = new ArrayList<LinkInfo>();
-      if( name.endsWith(".properties") )
-         parseLinkProperties(is, info, props);
-      else
-         throw new UnsupportedEncodingException("Unknown link format: "+name);
-      return info;
-   }
-
-   /**
-    * 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
-   {
-      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
-   {
-      String urispec = url.toExternalForm();
-      // Escape any spaces
-      urispec = urispec.replaceAll(" ", "%20");
-      return new URI(urispec);
-   }
-
-   /**
-    * 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 copy for file param.
-    *
-    * @param file the file
-    */
-   public static void enableCopy(VirtualFile file)
-   {
-      Map<String, String> options = getOptions(file);
-      if (options == null)
-         throw new IllegalArgumentException("Cannot enable copy on null options: " + file);
-
-      options.put(USE_COPY_QUERY, Boolean.TRUE.toString());
-   }
-
-   /**
-    * Disable copy for file param.
-    *
-    * @param file the file
-    */
-   public static void disableCopy(VirtualFile file)
-   {
-      Map<String, String> options = getOptions(file);
-      if (options == null)
-         throw new IllegalArgumentException("Cannot disable copy on null options: " + file);
-
-      options.remove(USE_COPY_QUERY);
-   }
-
-   /**
-    * Unpack the 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
-   {
-      if (file == null)
-         throw new IllegalArgumentException("Null file");
-      if (file.isLeaf())
-         return file;
-
-      VirtualFileHandler handler = file.getHandler();
-      // already unpacked
-      VirtualFileHandler unwrapped = handler;
-      if (unwrapped instanceof DelegatingHandler)
-         unwrapped = ((DelegatingHandler) unwrapped).getDelegate();
-
-      if (unwrapped instanceof ZipEntryHandler == false
-              && (unwrapped instanceof NestedJarHandler || unwrapped instanceof AbstractJarHandler == false))
-      {
-         if (log.isTraceEnabled())
-            log.trace("Should already be unpacked: " + file);
-         return file;
-      }
-
-      File guidDir = createTempDirectory(getTempDirectory(), GUID.asString());
-      File unpacked = createTempDirectory(guidDir, file.getName());
-
-      unpack(handler, unpacked, false);
-      FileSystemContext fileSystemContext = new FileSystemContext(unpacked);
-      VirtualFileHandler newHandler = fileSystemContext.getRoot();
-      VirtualFileHandler parent = handler.getParent();
-      if (parent != null)
-         parent.replaceChild(handler, newHandler);
-
-      return newHandler.getVirtualFile();
-   }
-
-   /**
-    * Create the temp directory.
-    *
-    * @param parent the parent
-    * @param name the dir name
-    * @return new directory
-    */
-   private 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
-    */
-   private static void unpack(VirtualFileHandler root, File file, boolean writeRoot) throws IOException
-   {
-      // should we write trhe root
-      if (writeRoot)
-         rewrite(root, file);
-
-      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
-    */
-   private 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)
-         {
-         }
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/VFSUtils.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,661 @@
+/*
+* 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.File;
+import java.io.FileOutputStream;
+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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+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.id.GUID;
+import org.jboss.virtual.plugins.context.file.FileHandler;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.spi.LinkInfo;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * VFS Utilities
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class VFSUtils
+{
+   /** The log */
+   private static final Logger log = Logger.getLogger(VFSUtils.class);
+   /** The link */
+   public static final String VFS_LINK_PREFIX = ".vfslink";
+   /** 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";
+
+   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")));
+      }
+   }
+
+   public synchronized static File getTempDirectory()
+   {
+      if (tempDir == null)
+      {
+         tempDir = AccessController.doPrivileged(new GetTempDir());
+         log.info("VFS temp dir: " + tempDir);
+      }
+      return tempDir;
+   }
+
+   /**
+    * 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)
+   {
+      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)
+         throw new IllegalStateException(file + " has no parent.");
+
+      URL parentURL;
+      URL vfsRootURL;
+      int rootPathLength;
+      try
+      {
+         parentURL = parent.toURL();
+         vfsRootURL = file.getVFS().getRoot().toURL();
+         rootPathLength = vfsRootURL.getPath().length();
+      }
+      catch(URISyntaxException e)
+      {
+         IOException ioe = new IOException("Failed to get parent URL for " + file);
+         ioe.initCause(e);
+         throw ioe;
+      }
+
+      StringTokenizer tokenizer = new StringTokenizer(classPath);
+      while (tokenizer.hasMoreTokens())
+      {
+         String path = tokenizer.nextToken();
+         try
+         {
+            String parentPath = parentURL.toString();
+            if(parentPath.endsWith("/") == false)
+               parentPath += "/";
+            URL libURL = new URL(parentPath + path);
+            String libPath = libURL.getPath();
+            // TODO, this occurs for inner jars. Doubtful that such a mf cp is valid
+            if( rootPathLength > libPath.length() )
+               throw new IOException("Invalid rootPath: "+vfsRootURL+", libPath: "+libPath);
+
+            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;
+      try
+      {
+         manifest = archive.findChild(JarFile.MANIFEST_NAME);
+      }
+      catch (IOException ignored)
+      {
+         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
+   {
+      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
+    {
+       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;
+   }
+
+   /**
+    * Get the name.
+    *
+    * @param uri the uri
+    * @return name from uri's path
+    */
+   public static String getName(URI 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 = new HashMap<String, String>();
+      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)
+   {
+      return name.indexOf(VFS_LINK_PREFIX) >= 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
+   {
+      List<LinkInfo> info = new ArrayList<LinkInfo>();
+      if( name.endsWith(".properties") )
+         parseLinkProperties(is, info, props);
+      else
+         throw new UnsupportedEncodingException("Unknown link format: "+name);
+      return info;
+   }
+
+   /**
+    * 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
+   {
+      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
+   {
+      String urispec = url.toExternalForm();
+      // Escape any spaces
+      urispec = urispec.replaceAll(" ", "%20");
+      return new URI(urispec);
+   }
+
+   /**
+    * 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 copy for file param.
+    *
+    * @param file the file
+    */
+   public static void enableCopy(VirtualFile file)
+   {
+      Map<String, String> options = getOptions(file);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot enable copy on null options: " + file);
+
+      options.put(USE_COPY_QUERY, Boolean.TRUE.toString());
+   }
+
+   /**
+    * Disable copy for file param.
+    *
+    * @param file the file
+    */
+   public static void disableCopy(VirtualFile file)
+   {
+      Map<String, String> options = getOptions(file);
+      if (options == null)
+         throw new IllegalArgumentException("Cannot disable copy on null options: " + file);
+
+      options.remove(USE_COPY_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 createTemp(file, true);
+   }
+
+   /**
+    * 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 createTemp(file, false);
+   }
+
+   /**
+    * Create temp.
+    *
+    * @param file the file to unpack/explode
+    * @param force should we force the creation
+    * @return temp file
+    * @throws IOException for any io error
+    * @throws URISyntaxException for any uri error
+    */
+   private static VirtualFile createTemp(VirtualFile file, boolean force) throws IOException, URISyntaxException
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+      if (file.isLeaf())
+         return file;
+
+      VirtualFileHandler handler = file.getHandler();
+      VirtualFileHandler unwrapped = handler;
+      if (handler instanceof DelegatingHandler)
+         unwrapped = ((DelegatingHandler)handler).getDelegate();
+
+      boolean ignoreTempCreation = false;
+      if (force)
+         ignoreTempCreation = (unwrapped.isNested() == false);
+
+      if (ignoreTempCreation || unwrapped instanceof FileHandler)
+      {
+         if (log.isTraceEnabled())
+            log.trace("Should already be unpacked/exploded: " + file);
+         return file;
+      }
+
+      File guidDir = createTempDirectory(getTempDirectory(), GUID.asString());
+      File unpacked = createTempDirectory(guidDir, file.getName());
+
+      unpack(handler, unpacked, false);
+      FileSystemContext fileSystemContext = new FileSystemContext(unpacked);
+      VirtualFileHandler newHandler = fileSystemContext.getRoot();
+      VirtualFileHandler parent = handler.getParent();
+      if (parent != null)
+         parent.replaceChild(handler, newHandler);
+
+      return newHandler.getVirtualFile();
+   }
+
+   /**
+    * Create the temp directory.
+    *
+    * @param parent the parent
+    * @param name the dir name
+    * @return new directory
+    */
+   private 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
+    */
+   private static void unpack(VirtualFileHandler root, File file, boolean writeRoot) throws IOException
+   {
+      // should we write trhe root
+      if (writeRoot)
+         rewrite(root, file);
+
+      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
+    */
+   private 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)
+         {
+         }
+      }
+   }
+
+   /**
+    * 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
+   {
+      VirtualFileHandler handler = file.getHandler();
+      return handler.isNested();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,584 +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
- * @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 vfsPath */
-   private transient String vfsPath;
-
-   /** The vfs URL */
-   private URL vfsUrl;
-
-   /** 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 (cachedLastModified != last)
-      {
-         hasBeenModified = cachedLastModified != 0;
-         cachedLastModified = last;
-      }
-      return hasBeenModified;
-   }
-
-   public String getName()
-   {
-      return name;
-   }
-
-   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;
-   }
-
-   public String getLocalPathName()
-   {
-      try
-      {
-         VirtualFileHandler handler = getVFSContext().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(rootPathName.length() + 1);
-         else
-            return "";
-      }
-      catch (IOException ex)
-      {
-         log.warn("Failed to compose local path name: context: " + getVFSContext() + ", 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);
-   }
-   
-   public VirtualFileHandler getParent() throws IOException
-   {
-      checkClosed();
-      return parent;
-   }
-   
-   public VFSContext getVFSContext()
-   {
-      checkClosed();
-      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 " + this);
-   }
-   
-   public void close() 
-   {
-      if (decrement() == 0)
-         doClose();
-   }
-
-   /**
-    * The real close
-    */
-   protected void doClose()
-   {
-      // nothing
-   }
-
-   /**
-    * 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
-      String[] tokens = PathTokenizer.getTokens(path);
-      if (tokens == null || tokens.length == 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.length; ++i)
-      {
-         if (current == null || current.isLeaf())
-            return null;
-
-         if (PathTokenizer.isCurrentToken(tokens[i]) == false)
-         {
-            if (PathTokenizer.isReverseToken(tokens[i]))
-            {
-               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;
-            }
-            else if (current instanceof StructuredVirtualFileHandler)
-            {
-               StructuredVirtualFileHandler structured = (StructuredVirtualFileHandler) current;
-               current = structured.createChildHandler(tokens[i]);
-            }
-            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(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", this.getVFSContext().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.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,584 @@
+/*
+* 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
+ * @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 vfsPath */
+   private transient String vfsPath;
+
+   /** The vfs URL */
+   private URL vfsUrl;
+
+   /** 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 (cachedLastModified != last)
+      {
+         hasBeenModified = cachedLastModified != 0;
+         cachedLastModified = last;
+      }
+      return hasBeenModified;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   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;
+   }
+
+   public String getLocalPathName()
+   {
+      try
+      {
+         VirtualFileHandler handler = getVFSContext().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: " + getVFSContext() + ", 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);
+   }
+   
+   public VirtualFileHandler getParent() throws IOException
+   {
+      checkClosed();
+      return parent;
+   }
+   
+   public VFSContext getVFSContext()
+   {
+      checkClosed();
+      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 " + this);
+   }
+   
+   public void close() 
+   {
+      if (decrement() == 0)
+         doClose();
+   }
+
+   /**
+    * The real close
+    */
+   protected void doClose()
+   {
+      // nothing
+   }
+
+   /**
+    * 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
+      String[] tokens = PathTokenizer.getTokens(path);
+      if (tokens == null || tokens.length == 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.length; ++i)
+      {
+         if (current == null || current.isLeaf())
+            return null;
+
+         if (PathTokenizer.isCurrentToken(tokens[i]) == false)
+         {
+            if (PathTokenizer.isReverseToken(tokens[i]))
+            {
+               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;
+            }
+            else if (current instanceof StructuredVirtualFileHandler)
+            {
+               StructuredVirtualFileHandler structured = (StructuredVirtualFileHandler) current;
+               current = structured.createChildHandler(tokens[i]);
+            }
+            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(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", this.getVFSContext().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.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,176 +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.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);
-      //if (delegate == null)
-      //   throw new IllegalArgumentException("Null delegate");
-      this.delegate = delegate;
-   }
-
-   public void setDelegate(VirtualFileHandler handler)
-   {
-      this.delegate = handler;
-   }
-
-   public VirtualFileHandler getDelegate()
-   {
-      return delegate;
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return delegate.getChild(path);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return delegate.getChildren(ignoreErrors);
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return delegate.getLastModified();
-   }
-
-   public long getSize() throws IOException
-   {
-      return delegate.getSize();
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      return delegate.isLeaf();
-   }
-
-   public boolean exists() throws IOException
-   {
-      return delegate.exists();
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      return delegate.isHidden();
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      return delegate.openStream();
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return delegate.toURI();
-   }
-
-   public URL toURL() throws URISyntaxException, MalformedURLException
-   {
-      return delegate.toURL();
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      delegate.replaceChild(original, replacement);
-   }
-
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      return delegate.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 DelegatingHandler)
-      {
-         DelegatingHandler handler = (DelegatingHandler) o;
-         if (delegate != null)
-            return delegate.equals(handler.delegate);
-         else if (handler.delegate != null)
-            return false;   // one is null
-         else
-            return true;    // both are null
-      }
-
-      return false;
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,181 @@
+/*
+ * 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.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);
+      //if (delegate == null)
+      //   throw new IllegalArgumentException("Null delegate");
+      this.delegate = delegate;
+   }
+
+   public void setDelegate(VirtualFileHandler handler)
+   {
+      this.delegate = handler;
+   }
+
+   public VirtualFileHandler getDelegate()
+   {
+      return delegate;
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return delegate.getChild(path);
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return delegate.getChildren(ignoreErrors);
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return delegate.getLastModified();
+   }
+
+   public long getSize() throws IOException
+   {
+      return delegate.getSize();
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      return delegate.isLeaf();
+   }
+
+   public boolean exists() throws IOException
+   {
+      return delegate.exists();
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return delegate.isHidden();
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return delegate.isNested();
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      return delegate.openStream();
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return delegate.toURI();
+   }
+
+   public URL toURL() throws URISyntaxException, MalformedURLException
+   {
+      return delegate.toURL();
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      delegate.replaceChild(original, replacement);
+   }
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      return delegate.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 DelegatingHandler)
+      {
+         DelegatingHandler handler = (DelegatingHandler) o;
+         if (delegate != null)
+            return delegate.equals(handler.delegate);
+         else if (handler.delegate != null)
+            return false;   // one is null
+         else
+            return true;    // both are null
+      }
+
+      return false;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,232 +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.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
- * @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));
-   }
-   /**
-    * 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());
-   }
-
-   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();
-   }
-
-   @Override
-   public long getSize()
-   {
-      return getFile().length();
-   }
-
-   public boolean isLeaf()
-   {
-      return getFile().isFile();
-   }
-
-   public boolean isHidden()
-   {
-      return getFile().isHidden();
-   }
-
-   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);
-            }
-            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);
-         childCache.put(name, handler);
-      }
-      return handler;
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   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.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,237 @@
+/*
+* 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.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
+ * @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));
+   }
+   /**
+    * 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());
+   }
+
+   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();
+   }
+
+   @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 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);
+            }
+            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);
+         childCache.put(name, handler);
+      }
+      return handler;
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   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.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,223 +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.IOException;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.AbstractURLHandler;
-import org.jboss.virtual.plugins.context.DelegatingHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
-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;
-
-/**
- * A handler for link directories.
- * 
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.1 $
- */
-public class LinkHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
-{
-   private static final long serialVersionUID = 1;
-   /** The link information */
-   private List<LinkInfo> links;
-   /** The link targets */
-   private HashMap<String, VirtualFileHandler> linkTargets = new HashMap<String, VirtualFileHandler>(3);
-
-   class ParentOfLink extends AbstractURLHandler implements StructuredVirtualFileHandler
-   {
-      private static final long serialVersionUID = 1;
-
-      private HashMap<String, VirtualFileHandler> children = new HashMap<String, VirtualFileHandler>(1);
-
-      public ParentOfLink(VFSContext context, VirtualFileHandler parent, URL url, String name)
-      {
-         super(context, parent, url, name);
-         try
-         {
-            setVfsUrl(new URL("vfs" + url.toString()));
-         }
-         catch (MalformedURLException e)
-         {
-            throw new RuntimeException(e);
-         }
-      }
-
-      void addChild(VirtualFileHandler child, String name)
-      {
-         children.put(name, child);
-      }
-
-      public VirtualFileHandler createChildHandler(String name) throws IOException
-      {
-         return children.get(name);
-      }
-
-      public VirtualFileHandler getChild(String path) throws IOException
-      {
-         return structuredFindChild(path);
-      }
-
-      public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-      {
-         return null;
-      }
-
-      public boolean isLeaf() throws IOException
-      {
-         return false;
-      }
-   }
-
-   /**
-    * Create a new LinkHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param uri the uri
-    * @param name the name
-    * @param links the links
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url
-    * @throws URISyntaxException if the uri cannot be parsed
-    */
-   public LinkHandler(FileSystemContext context, VirtualFileHandler parent, URI uri, String name,
-         List<LinkInfo> links)
-      throws IOException, URISyntaxException
-   {
-      // TODO: This URL is not consistent with the getName, but does point to the raw link file
-      super(context, parent, uri.toURL(), name);
-      this.links = links;
-      setVfsUrl(new URL("vfs" + uri.toURL().toString()));
-      // Create handlers for the links and add
-      for(LinkInfo link : links)
-      {
-         String linkName = link.getName();
-         if( linkName == null )
-            linkName = VFSUtils.getName(link.getLinkTarget());
-         if( linkName != null )
-         {
-            String[] paths = PathTokenizer.getTokens(linkName);
-            int n = 0;
-            VirtualFileHandler linkParent = this;
-            String atom;
-            // Look for an existing parent
-            VirtualFileHandler previous;
-            for(; n < paths.length-1; n ++)
-            {
-               previous = linkParent;
-               atom = paths[n];
-               linkParent = previous.getChild(atom);
-               if (linkParent == null)
-               {
-                  linkParent = previous;
-                  break;
-               }
-            }
-            // Create any missing parents
-            for(; n < paths.length-1; n ++)
-            {
-               atom = paths[n];
-               URL polURL = new URL(linkParent.toURI().toURL(), atom);
-               ParentOfLink pol = new ParentOfLink(this.getVFSContext(), linkParent, polURL, atom);
-               if( linkParent == this )
-               {
-                  linkTargets.put(atom, pol);
-               }
-               else if (linkParent instanceof ParentOfLink)
-               {
-                  ParentOfLink prevPOL = (ParentOfLink) linkParent;
-                  prevPOL.addChild(pol, atom);
-               }
-               else
-               {
-                  throw new IOException("Link parent not ParentOfLink.");
-               }
-               linkParent = pol;
-            }
-               
-            // Create the link handler
-            atom = paths[n];
-            VirtualFileHandler linkHandler = createLinkHandler(linkParent, atom, link.getLinkTarget());
-            if( linkParent == this )
-            {
-               linkTargets.put(atom, linkHandler);
-            }
-            else if (linkParent instanceof ParentOfLink)
-            {
-               ParentOfLink prevPOL = (ParentOfLink) linkParent;
-               prevPOL.addChild(linkHandler, atom);
-            }            
-         }
-      }
-   }
-
-   public boolean isLeaf()
-   {
-      return false;
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return new ArrayList<VirtualFileHandler>(linkTargets.values());
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      return linkTargets.get(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   @Override
-   protected void doClose()
-   {
-      super.doClose();
-      links.clear();
-   }
-   
-   protected VirtualFileHandler createLinkHandler(VirtualFileHandler parent, String name, URI linkURI)
-      throws IOException
-   {
-      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(linkURI);
-      VFSContext context = factory.getVFS(linkURI);
-      VirtualFileHandler rootHandler = context.getRoot();
-      // Wrap the handler in a delegate so we can change the parent and name
-      // TODO: if the factory caches contexts the root handler may not point to the link
-      return new DelegatingHandler(this.getVFSContext(), parent, name, rootHandler);
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,233 @@
+/*
+* 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.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractURLHandler;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
+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;
+
+/**
+ * A handler for link directories.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 1.1 $
+ */
+public class LinkHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
+{
+   private static final long serialVersionUID = 1;
+   /** The link information */
+   private List<LinkInfo> links;
+   /** The link targets */
+   private HashMap<String, VirtualFileHandler> linkTargets = new HashMap<String, VirtualFileHandler>(3);
+
+   class ParentOfLink extends AbstractURLHandler implements StructuredVirtualFileHandler
+   {
+      private static final long serialVersionUID = 1;
+
+      private HashMap<String, VirtualFileHandler> children = new HashMap<String, VirtualFileHandler>(1);
+
+      public ParentOfLink(VFSContext context, VirtualFileHandler parent, URL url, String name)
+      {
+         super(context, parent, url, name);
+         try
+         {
+            setVfsUrl(new URL("vfs" + url.toString()));
+         }
+         catch (MalformedURLException e)
+         {
+            throw new RuntimeException(e);
+         }
+      }
+
+      void addChild(VirtualFileHandler child, String name)
+      {
+         children.put(name, child);
+      }
+
+      public VirtualFileHandler createChildHandler(String name) throws IOException
+      {
+         return children.get(name);
+      }
+
+      public VirtualFileHandler getChild(String path) throws IOException
+      {
+         return structuredFindChild(path);
+      }
+
+      public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+      {
+         return null;
+      }
+
+      public boolean isLeaf() throws IOException
+      {
+         return false;
+      }
+
+      public boolean isNested() throws IOException
+      {
+         return false;
+      }
+   }
+
+   /**
+    * Create a new LinkHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param uri the uri
+    * @param name the name
+    * @param links the links
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url
+    * @throws URISyntaxException if the uri cannot be parsed
+    */
+   public LinkHandler(FileSystemContext context, VirtualFileHandler parent, URI uri, String name,
+         List<LinkInfo> links)
+      throws IOException, URISyntaxException
+   {
+      // TODO: This URL is not consistent with the getName, but does point to the raw link file
+      super(context, parent, uri.toURL(), name);
+      this.links = links;
+      setVfsUrl(new URL("vfs" + uri.toURL().toString()));
+      // Create handlers for the links and add
+      for(LinkInfo link : links)
+      {
+         String linkName = link.getName();
+         if( linkName == null )
+            linkName = VFSUtils.getName(link.getLinkTarget());
+         if( linkName != null )
+         {
+            String[] paths = PathTokenizer.getTokens(linkName);
+            int n = 0;
+            VirtualFileHandler linkParent = this;
+            String atom;
+            // Look for an existing parent
+            VirtualFileHandler previous;
+            for(; n < paths.length-1; n ++)
+            {
+               previous = linkParent;
+               atom = paths[n];
+               linkParent = previous.getChild(atom);
+               if (linkParent == null)
+               {
+                  linkParent = previous;
+                  break;
+               }
+            }
+            // Create any missing parents
+            for(; n < paths.length-1; n ++)
+            {
+               atom = paths[n];
+               URL polURL = new URL(linkParent.toURI().toURL(), atom);
+               ParentOfLink pol = new ParentOfLink(this.getVFSContext(), linkParent, polURL, atom);
+               if( linkParent == this )
+               {
+                  linkTargets.put(atom, pol);
+               }
+               else if (linkParent instanceof ParentOfLink)
+               {
+                  ParentOfLink prevPOL = (ParentOfLink) linkParent;
+                  prevPOL.addChild(pol, atom);
+               }
+               else
+               {
+                  throw new IOException("Link parent not ParentOfLink.");
+               }
+               linkParent = pol;
+            }
+               
+            // Create the link handler
+            atom = paths[n];
+            VirtualFileHandler linkHandler = createLinkHandler(linkParent, atom, link.getLinkTarget());
+            if( linkParent == this )
+            {
+               linkTargets.put(atom, linkHandler);
+            }
+            else if (linkParent instanceof ParentOfLink)
+            {
+               ParentOfLink prevPOL = (ParentOfLink) linkParent;
+               prevPOL.addChild(linkHandler, atom);
+            }            
+         }
+      }
+   }
+
+   public boolean isLeaf()
+   {
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return new ArrayList<VirtualFileHandler>(linkTargets.values());
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      return linkTargets.get(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   @Override
+   protected void doClose()
+   {
+      super.doClose();
+      links.clear();
+   }
+   
+   protected VirtualFileHandler createLinkHandler(VirtualFileHandler parent, String name, URI linkURI)
+      throws IOException
+   {
+      VFSContextFactory factory = VFSContextFactoryLocator.getFactory(linkURI);
+      VFSContext context = factory.getVFS(linkURI);
+      VirtualFileHandler rootHandler = context.getRoot();
+      // Wrap the handler in a delegate so we can change the parent and name
+      // TODO: if the factory caches contexts the root handler may not point to the link
+      return new DelegatingHandler(this.getVFSContext(), parent, name, rootHandler);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,279 +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.jar;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-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 java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * A nested jar contents implementation used to represent a jar within a jar.
- *
- * @author Ales.Justin at jboss.org
- * @author Scott.Stark at jboss.org
- */
-public class JarEntryContents extends AbstractJarHandler implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
-{
-   /**
-    * serialVersionUID
-    */
-   private static final long serialVersionUID = 1L;
-
-   private URL entryURL;
-   private byte[] contents;
-   private boolean isJar;
-   private NestedJarFromStream njar;
-   private InputStream openStream;
-
-   private List<VirtualFileHandler> entryChildren;
-   private transient Map<String, VirtualFileHandler> entryMap;
-
-   JarEntryContents(VFSContext context, VirtualFileHandler parent, ZipEntry entry, String entryName, URL jarURL, URL entryURL, byte[] contents)
-           throws IOException
-   {
-      super(context, parent, jarURL, null, entry, entryName);
-      try
-      {
-         setPathName(getChildPathName(entryName, false));
-         setVfsUrl(getChildVfsUrl(entryName, false));
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException(e);
-      }
-      this.entryURL = entryURL;
-      this.isJar = JarUtils.isArchive(getName());
-      this.contents = contents;
-   }
-
-   protected void initCacheLastModified()
-   {
-   }
-
-   /**
-    * Add a child to an entry
-    *
-    * @param child the child
-    */
-   public synchronized void addChild(VirtualFileHandler child)
-   {
-      if (entryChildren == null)
-         entryChildren = new ArrayList<VirtualFileHandler>();
-      entryChildren.add(child);
-      if (entryMap != null)
-         entryMap.put(child.getName(), child);
-   }
-
-   /**
-    * TODO: removing the entry/jar that resulted in this needs
-    * to be detected.
-    */
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      return false;
-   }
-
-   byte[] getContents()
-   {
-      return contents;
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      List<VirtualFileHandler> children;
-
-      if (isJar)
-      {
-         initNestedJar();
-         children = njar.getChildren(ignoreErrors);
-      }
-      else
-      {
-         children = entryChildren;
-      }
-
-      if (children == null)
-         return Collections.emptyList();
-      else
-         return Collections.unmodifiableList(children);
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      if (isJar)
-      {
-         initNestedJar();
-         return njar.createChildHandler(name);
-      }
-      else
-         return findChildHandler(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-
-      if ("".equals(path))
-         return this;
-
-      if (isJar)
-      {
-         initNestedJar();
-         return njar.getChild(path);
-      }
-      else if (getEntry().isDirectory())
-      {
-         return structuredFindChild(path);
-      }
-      return null;
-   }
-
-   /**
-    * Find the handler.
-    * TODO: synchronization on lazy entryMap creation
-    *
-    * @param name the path name
-    * @return handler or <code>null</code> is it doesn't exist
-    * @throws IOException for any error
-    */
-   protected synchronized VirtualFileHandler findChildHandler(String name) throws IOException
-   {
-      if (entryChildren == null)
-         return null;
-
-      if (entryMap == null)
-      {
-         entryMap = new HashMap<String, VirtualFileHandler>();
-         for (VirtualFileHandler child : entryChildren)
-            entryMap.put(child.getName(), child);
-      }
-      return entryMap.get(name);
-   }
-
-   // Convience attribute accessors
-   public long getLastModified()
-   {
-      return getEntry().getTime();
-   }
-
-   public long getSize()
-   {
-      return getEntry().getSize();
-   }
-
-   public boolean isLeaf()
-   {
-      return isJar == false && getEntry().isDirectory() == false;
-   }
-
-   // Stream accessor
-   public synchronized InputStream openStream() throws IOException
-   {
-      initNestedJar();
-      if (njar != null)
-         openStream = njar.openStream();
-      else
-         openStream = new ByteArrayInputStream(contents);
-      return openStream;
-   }
-
-   public synchronized void close()
-   {
-      if (openStream != null)
-      {
-         try
-         {
-            openStream.close();
-         }
-         catch (IOException e)
-         {
-            log.error("close error", e);
-         }
-         openStream = null;
-      }
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return entryURL.toURI();
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      entryChildren.remove(original);
-      entryChildren.add(replacement);
-      entryMap.put(original.getName(), replacement);
-   }
-
-   public String toString()
-   {
-      StringBuffer tmp = new StringBuffer(super.toString());
-      tmp.append('[');
-      tmp.append("name=");
-      tmp.append(getName());
-      tmp.append(",size=");
-      tmp.append(getSize());
-      tmp.append(",time=");
-      tmp.append(getLastModified());
-      tmp.append(",URI=");
-      try
-      {
-         tmp.append(toURI());
-      }
-      catch (URISyntaxException ignored)
-      {
-      }
-      tmp.append(']');
-      return tmp.toString();
-   }
-
-   protected synchronized void initNestedJar() throws IOException
-   {
-      if (isJar && njar == null)
-      {
-         ByteArrayInputStream bais = new ByteArrayInputStream(contents);
-         ZipInputStream zis = new ZipInputStream(bais);
-         njar = new NestedJarFromStream(getVFSContext(), getParent(), zis, entryURL, null, getEntry(), getName());
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryContents.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,291 @@
+/*
+* 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.jar;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+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 java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * A nested jar contents implementation used to represent a jar within a jar.
+ *
+ * @author Ales.Justin at jboss.org
+ * @author Scott.Stark at jboss.org
+ */
+public class JarEntryContents extends AbstractJarHandler implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
+{
+   /**
+    * serialVersionUID
+    */
+   private static final long serialVersionUID = 1L;
+
+   private URL entryURL;
+   private byte[] contents;
+   private boolean isJar;
+   private NestedJarFromStream njar;
+   private InputStream openStream;
+
+   private List<VirtualFileHandler> entryChildren;
+   private transient Map<String, VirtualFileHandler> entryMap;
+
+   JarEntryContents(VFSContext context, VirtualFileHandler parent, ZipEntry entry, String entryName, URL jarURL, URL entryURL, byte[] contents)
+           throws IOException
+   {
+      super(context, parent, jarURL, null, entry, entryName);
+      try
+      {
+         setPathName(getChildPathName(entryName, false));
+         setVfsUrl(getChildVfsUrl(entryName, false));
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+      this.entryURL = entryURL;
+      this.isJar = JarUtils.isArchive(getName());
+      this.contents = contents;
+   }
+
+   protected void initCacheLastModified()
+   {
+   }
+
+   /**
+    * Add a child to an entry
+    *
+    * @param child the child
+    */
+   public synchronized void addChild(VirtualFileHandler child)
+   {
+      if (entryChildren == null)
+         entryChildren = new ArrayList<VirtualFileHandler>();
+      entryChildren.add(child);
+      if (entryMap != null)
+         entryMap.put(child.getName(), child);
+   }
+
+   /**
+    * TODO: removing the entry/jar that resulted in this needs
+    * to be detected.
+    */
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return true;
+   }
+
+   byte[] getContents()
+   {
+      return contents;
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      List<VirtualFileHandler> children;
+
+      if (isJar)
+      {
+         initNestedJar();
+         children = njar.getChildren(ignoreErrors);
+      }
+      else
+      {
+         children = entryChildren;
+      }
+
+      if (children == null)
+         return Collections.emptyList();
+      else
+         return Collections.unmodifiableList(children);
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      if (isJar)
+      {
+         initNestedJar();
+         return njar.createChildHandler(name);
+      }
+      else
+         return findChildHandler(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+
+      if ("".equals(path))
+         return this;
+
+      if (isJar)
+      {
+         initNestedJar();
+         return njar.getChild(path);
+      }
+      else if (getEntry().isDirectory())
+      {
+         return structuredFindChild(path);
+      }
+      return null;
+   }
+
+   /**
+    * Find the handler.
+    * TODO: synchronization on lazy entryMap creation
+    *
+    * @param name the path name
+    * @return handler or <code>null</code> is it doesn't exist
+    * @throws IOException for any error
+    */
+   protected synchronized VirtualFileHandler findChildHandler(String name) throws IOException
+   {
+      if (entryChildren == null)
+         return null;
+
+      if (entryMap == null)
+      {
+         entryMap = new HashMap<String, VirtualFileHandler>();
+         for (VirtualFileHandler child : entryChildren)
+            entryMap.put(child.getName(), child);
+      }
+      return entryMap.get(name);
+   }
+
+   // Convience attribute accessors
+   public long getLastModified()
+   {
+      return getEntry().getTime();
+   }
+
+   public long getSize()
+   {
+      return getEntry().getSize();
+   }
+
+   public boolean isLeaf()
+   {
+      return isJar == false && getEntry().isDirectory() == false;
+   }
+
+   // Stream accessor
+   public synchronized InputStream openStream() throws IOException
+   {
+      initNestedJar();
+      if (njar != null)
+         openStream = njar.openStream();
+      else
+         openStream = new ByteArrayInputStream(contents);
+      return openStream;
+   }
+
+   public synchronized void close()
+   {
+      if (openStream != null)
+      {
+         try
+         {
+            openStream.close();
+         }
+         catch (IOException e)
+         {
+            log.error("close error", e);
+         }
+         openStream = null;
+      }
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return entryURL.toURI();
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      if (isJar)
+      {
+         njar.internalReplaceChild(original, replacement);
+      }
+      else
+      {
+         entryChildren.remove(original);
+         entryChildren.add(replacement);
+         entryMap.put(original.getName(), replacement);
+      }
+   }
+
+   public String toString()
+   {
+      StringBuffer tmp = new StringBuffer(super.toString());
+      tmp.append('[');
+      tmp.append("name=");
+      tmp.append(getName());
+      tmp.append(",size=");
+      tmp.append(getSize());
+      tmp.append(",time=");
+      tmp.append(getLastModified());
+      tmp.append(",URI=");
+      try
+      {
+         tmp.append(toURI());
+      }
+      catch (URISyntaxException ignored)
+      {
+      }
+      tmp.append(']');
+      return tmp.toString();
+   }
+
+   protected synchronized void initNestedJar() throws IOException
+   {
+      if (isJar && njar == null)
+      {
+         ByteArrayInputStream bais = new ByteArrayInputStream(contents);
+         ZipInputStream zis = new ZipInputStream(bais);
+         njar = new NestedJarFromStream(getVFSContext(), getParent(), zis, entryURL, null, getEntry(), getName());
+      }
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,175 +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.jar;
-
-import java.io.IOException;
-import java.io.InputStream;
-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 java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-
-import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * JarEntryHandler.
- * TODO: JBVFS-7
- *
- * @author <a href="ales.justin at jboss.org">Ales Justin</a>
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.1 $
- */
-public class JarEntryHandler extends AbstractJarHandler implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
-{
-   /**
-    * serialVersionUID
-    */
-   private static final long serialVersionUID = 1L;
-
-   private List<VirtualFileHandler> entryChildren;
-   private transient Map<String, VirtualFileHandler> entryMap;
-
-   /**
-    * Create a new JarHandler.
-    *
-    * @param context   the context
-    * @param parent    the parent
-    * @param jar       the jar file
-    * @param entry     the entry
-    * @param entryName the entry name
-    * @param url       the url
-    * @throws IOException              for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url, jar or entry
-    */
-   public JarEntryHandler(VFSContext context, VirtualFileHandler parent, JarFile jar, ZipEntry entry, String entryName, URL url)
-         throws IOException
-   {
-      super(context, parent, url, jar, entry, entryName);
-      try
-      {
-         setVfsUrl(getChildVfsUrl(entryName, entry.isDirectory()));
-      }
-      catch (URISyntaxException e)
-      {
-         throw new RuntimeException(e);
-      }
-   }
-
-   @Override
-   protected void initCacheLastModified()
-   {
-      // complete
-   }
-
-   @Override
-   public boolean hasBeenModified() throws IOException
-   {
-      return false; // right now, jar entries should always 
-   }
-
-   /**
-    * Add a child to an entry
-    *
-    * @param child the child
-    */
-   public void addChild(VirtualFileHandler child)
-   {
-      if (entryChildren == null)
-         entryChildren = new ArrayList<VirtualFileHandler>();
-      entryChildren.add(child);
-      if (entryMap != null)
-         entryMap.put(child.getName(), child);
-   }
-
-   @Override
-   public long getLastModified()
-   {
-      return getEntry().getTime();
-   }
-
-   @Override
-   public long getSize()
-   {
-      return getEntry().getSize();
-   }
-
-   public boolean isLeaf()
-   {
-      return getEntry().isDirectory() == false;
-   }
-
-   public boolean isHidden()
-   {
-      checkClosed();
-      return false;
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      checkClosed();
-      if (entryChildren == null)
-         return Collections.emptyList();
-      return Collections.unmodifiableList(entryChildren);
-   }
-
-   @Override
-   public InputStream openStream() throws IOException
-   {
-      return getJar().getInputStream(getEntry());
-   }
-
-   // TODO: synchronization on lazy entryMap creation
-   public synchronized VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      if (entryChildren == null)
-         return null;
-
-      if (entryMap == null)
-      {
-         entryMap = new HashMap<String, VirtualFileHandler>();
-         for (VirtualFileHandler child : entryChildren)
-            entryMap.put(child.getName(), child);
-      }
-      return entryMap.get(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      entryChildren.remove(original);
-      entryChildren.add(replacement);
-      entryMap.put(original.getName(), replacement);
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,180 @@
+/*
+* 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.jar;
+
+import java.io.IOException;
+import java.io.InputStream;
+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 java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * JarEntryHandler.
+ * TODO: JBVFS-7
+ *
+ * @author <a href="ales.justin at jboss.org">Ales Justin</a>
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 1.1 $
+ */
+public class JarEntryHandler extends AbstractJarHandler implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
+{
+   /**
+    * serialVersionUID
+    */
+   private static final long serialVersionUID = 1L;
+
+   private List<VirtualFileHandler> entryChildren;
+   private transient Map<String, VirtualFileHandler> entryMap;
+
+   /**
+    * Create a new JarHandler.
+    *
+    * @param context   the context
+    * @param parent    the parent
+    * @param jar       the jar file
+    * @param entry     the entry
+    * @param entryName the entry name
+    * @param url       the url
+    * @throws IOException              for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url, jar or entry
+    */
+   public JarEntryHandler(VFSContext context, VirtualFileHandler parent, JarFile jar, ZipEntry entry, String entryName, URL url)
+         throws IOException
+   {
+      super(context, parent, url, jar, entry, entryName);
+      try
+      {
+         setVfsUrl(getChildVfsUrl(entryName, entry.isDirectory()));
+      }
+      catch (URISyntaxException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+   @Override
+   protected void initCacheLastModified()
+   {
+      // complete
+   }
+
+   @Override
+   public boolean hasBeenModified() throws IOException
+   {
+      return false; // right now, jar entries should always 
+   }
+
+   /**
+    * Add a child to an entry
+    *
+    * @param child the child
+    */
+   public void addChild(VirtualFileHandler child)
+   {
+      if (entryChildren == null)
+         entryChildren = new ArrayList<VirtualFileHandler>();
+      entryChildren.add(child);
+      if (entryMap != null)
+         entryMap.put(child.getName(), child);
+   }
+
+   @Override
+   public long getLastModified()
+   {
+      return getEntry().getTime();
+   }
+
+   @Override
+   public long getSize()
+   {
+      return getEntry().getSize();
+   }
+
+   public boolean isLeaf()
+   {
+      return getEntry().isDirectory() == false;
+   }
+
+   public boolean isHidden()
+   {
+      checkClosed();
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return true;
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      checkClosed();
+      if (entryChildren == null)
+         return Collections.emptyList();
+      return Collections.unmodifiableList(entryChildren);
+   }
+
+   @Override
+   public InputStream openStream() throws IOException
+   {
+      return getJar().getInputStream(getEntry());
+   }
+
+   // TODO: synchronization on lazy entryMap creation
+   public synchronized VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      if (entryChildren == null)
+         return null;
+
+      if (entryMap == null)
+      {
+         entryMap = new HashMap<String, VirtualFileHandler>();
+         for (VirtualFileHandler child : entryChildren)
+            entryMap.put(child.getName(), child);
+      }
+      return entryMap.get(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      entryChildren.remove(original);
+      entryChildren.add(replacement);
+      entryMap.put(original.getName(), replacement);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,89 +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.jar;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.JarURLConnection;
-import java.net.URL;
-import java.util.jar.JarFile;
-
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * JarHandler.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class JarHandler extends AbstractStructuredJarHandler<Object>
-{
-   /** serialVersionUID */
-   private static final long serialVersionUID = 1L;
-
-   /**
-    * Create a new JarHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param url the url
-    * @param name the name
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url or vfsPath
-    */
-   public JarHandler(VFSContext context, VirtualFileHandler parent, URL url, String name) throws IOException
-   {
-      super(context, parent, url, ((JarURLConnection) url.openConnection()).getJarFile(), null, name);
-      setVfsUrl(new URL("vfs" + url));
-
-      try
-      {
-         initJarFile();
-      }
-      catch (IOException original)
-      {
-         // Fix the context of the error message
-         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
-         e.setStackTrace(original.getStackTrace());
-         throw e;
-      }
-   }
-
-   public JarHandler(VFSContext context, VirtualFileHandler parent, File file, URL url, String name) throws IOException
-   {
-      super(context, parent, url, new JarFile(file), null, name);
-      setVfsUrl(new URL("vfs" + url));
-
-      try
-      {
-         initJarFile();
-      }
-      catch (IOException original)
-      {
-         // Fix the context of the error message
-         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
-         e.setStackTrace(original.getStackTrace());
-         throw e;
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/JarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,94 @@
+/*
+* 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.jar;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.jar.JarFile;
+
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * JarHandler.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class JarHandler extends AbstractStructuredJarHandler<Object>
+{
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+
+   /**
+    * Create a new JarHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param url the url
+    * @param name the name
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url or vfsPath
+    */
+   public JarHandler(VFSContext context, VirtualFileHandler parent, URL url, String name) throws IOException
+   {
+      super(context, parent, url, ((JarURLConnection) url.openConnection()).getJarFile(), null, name);
+      setVfsUrl(new URL("vfs" + url));
+
+      try
+      {
+         initJarFile();
+      }
+      catch (IOException original)
+      {
+         // Fix the context of the error message
+         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
+         e.setStackTrace(original.getStackTrace());
+         throw e;
+      }
+   }
+
+   public JarHandler(VFSContext context, VirtualFileHandler parent, File file, URL url, String name) throws IOException
+   {
+      super(context, parent, url, new JarFile(file), null, name);
+      setVfsUrl(new URL("vfs" + url));
+
+      try
+      {
+         initJarFile();
+      }
+      catch (IOException original)
+      {
+         // Fix the context of the error message
+         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
+         e.setStackTrace(original.getStackTrace());
+         throw e;
+      }
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,394 +0,0 @@
-/*
- * Copyright (c) 2005 Your Corporation. All Rights Reserved.
- */
-package org.jboss.virtual.plugins.context.jar;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-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.Enumeration;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * A nested jar implementation used to represent a jar within a jar.
- *
- * @author Ales.Justin at jboss.org
- * @author Scott.Stark at jboss.org
- * @version $Revision: 44334 $
- */
-public class NestedJarFromStream extends AbstractStructuredJarHandler<byte[]>
-{
-   /**
-    * serialVersionUID
-    */
-   private static final long serialVersionUID = 2L;
-   /** The class serial fields */
-   private static final ObjectStreamField[] serialPersistentFields = {
-      new ObjectStreamField("zisBytes", byte[].class),
-      new ObjectStreamField("jarURL", URL.class),
-      new ObjectStreamField("entryURL", String.class),
-      new ObjectStreamField("lastModified", long.class),
-      new ObjectStreamField("size", long.class)
-   };
-
-   private transient ZipInputStream zis;
-   private transient AtomicBoolean inited = new AtomicBoolean(false);
-   private URL jarURL;
-   private URL entryURL;
-   private long lastModified;
-   private long size;
-
-   /**
-    * Create a nested jar from the parent zip inputstream/zip entry.
-    *
-    * @param context   - the context containing the jar
-    * @param parent    - the jar handler for this nested jar
-    * @param zis       - the jar zip input stream
-    * @param jarURL    - the URL to use as the jar URL
-    * @param jar       - the parent jar file for the nested jar
-    * @param entry     - the zip entry
-    * @param entryName - the entry name
-    * @throws IOException for any error
-    */
-   public NestedJarFromStream(VFSContext context, VirtualFileHandler parent, ZipInputStream zis, URL jarURL, JarFile jar, ZipEntry entry, String entryName) throws IOException
-   {
-      super(context, parent, jarURL, jar, entry, entryName);
-      this.jarURL = jarURL;
-      this.lastModified = entry.getTime();
-      this.size = entry.getSize();
-      this.zis = zis;
-      try
-      {
-         setPathName(getChildPathName(entryName, false));
-         setVfsUrl(getChildVfsUrl(entryName, false));
-      }
-      catch (Exception e)
-      {
-         throw new RuntimeException(e);
-      }
-   }
-
-   protected void initCacheLastModified()
-   {
-      cachedLastModified = lastModified;
-   }
-
-   /**
-    * Initialize entries.
-    *
-    * @throws IOException for any error
-    */
-   protected void init() throws IOException
-   {
-      if (inited.get() == false)
-      {
-         inited.set(true);
-         try
-         {
-            initJarFile(new ZisEnumeration());
-         }
-         finally
-         {
-            close();
-         }
-      }
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      init();
-      return super.getChildren(ignoreErrors);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      init();
-      return super.getChild(path);
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      init();
-      return super.createChildHandler(name);
-   }
-
-   protected void extraWrapperInfo(ZipEntryWrapper<byte[]> wrapper) throws IOException
-   {
-      byte[] contents;
-      int size = (int)wrapper.getSize();
-      if (size != 0)
-      {
-         ByteArrayOutputStream baos = size > 0 ? new ByteArrayOutputStream(size) : new ByteArrayOutputStream();
-         byte[] tmp = new byte[1024];
-         while (zis.available() > 0)
-         {
-            int length = zis.read(tmp);
-            if (length > 0)
-               baos.write(tmp, 0, length);
-         }
-         contents = baos.toByteArray();
-      }
-      else
-         contents = new byte[0];
-      wrapper.setExtra(contents);
-   }
-
-   protected VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, ZipEntryWrapper<byte[]> wrapper, String entryName) throws IOException
-   {
-      try
-      {
-         String url = toURI().toASCIIString() + "!/" + wrapper.getName();
-         URL jecURL = new URL(url);
-         VFSContext context = parent.getVFSContext();
-         if (wrapper.isDirectory())
-         {
-            return new SynthenticDirEntryHandler(context, parent, entryName, System.currentTimeMillis(), jecURL);  
-         }
-         else
-         {
-            byte[] contents = wrapper.getExtra();
-            return new JarEntryContents(context, parent, wrapper.getEntry(), entryName, toURL(), jecURL, contents);
-         }
-      }
-      catch (Throwable t)
-      {
-         IOException ioe = new IOException("Exception while reading nested jar entry: " + this);
-         ioe.initCause(t);
-         ioe.setStackTrace(t.getStackTrace());
-         throw ioe;
-      }
-   }
-
-   /**
-    * TODO: removing the entry/jar that resulted in this needs
-    * to be detected.
-    */
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isHidden()
-   {
-      return false;
-   }
-
-   public long getSize()
-   {
-      return size;
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return lastModified;
-   }
-
-   // Stream accessor
-   public InputStream openStream() throws IOException
-   {
-      if(zis == null)
-      {
-         // Need to obtain this nested jar input stream from parent
-         InputStream parentIS = super.getParent().openStream();
-         if(parentIS == null)
-            throw new IOException("Failed to open parent stream, "+this);
-         if(parentIS instanceof ZipInputStream)
-         {
-            zis = (ZipInputStream) parentIS;
-         }
-         else
-         {
-            zis = new ZipInputStream(parentIS);
-         }
-         // First find our entry
-         ZipEntry entry = zis.getNextEntry();
-         while(entry != null)
-         {
-            if(entry.getName().equals(getName()))
-               break;
-            entry = zis.getNextEntry();
-         }
-         if(entry == null)
-            throw new IOException("Failed to find nested jar entry: "+this.getName()+" in parent: "+getParent());
-      }
-      return zis;
-   }
-
-   public void close()
-   {
-      if (zis != null)
-      {
-         try
-         {
-            zis.close();
-         }
-         catch (IOException e)
-         {
-            log.error("close error", e);
-         }
-         zis = null;
-      }
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      try
-      {
-         if (entryURL == null)
-            entryURL = new URL(jarURL, getName());
-      }
-      catch (MalformedURLException e)
-      {
-         throw new URISyntaxException("Failed to create relative jarURL", e.getMessage());
-      }
-      return entryURL.toURI();
-   }
-
-   public String toString()
-   {
-      StringBuffer tmp = new StringBuffer(super.toString());
-      tmp.append('[');
-      tmp.append("name=");
-      tmp.append(getName());
-      tmp.append(",size=");
-      tmp.append(getSize());
-      tmp.append(",lastModified=");
-      tmp.append(lastModified);
-      tmp.append(",URI=");
-      try
-      {
-         tmp.append(toURI());
-      }
-      catch (URISyntaxException e)
-      {
-      }
-      tmp.append(']');
-      return tmp.toString();
-   }
-
-   protected void initJarFile() throws IOException
-   {
-      // todo - deserialize
-   }
-
-   private class ZisEnumeration implements Enumeration<ZipEntryWrapper<byte[]>>
-   {
-      private boolean moved = true;
-      private ZipEntry next = null;
-
-      public boolean hasMoreElements()
-      {
-         if (zis == null)
-            return false;
-         
-         try
-         {
-            if (moved)
-            {
-               next = zis.getNextEntry();
-               moved = false;
-            }
-            return next != null;
-         }
-         catch (IOException e)
-         {
-            throw new RuntimeException(e);
-         }
-      }
-
-      public ZipEntryWrapper<byte[]> nextElement()
-      {
-         moved = true;
-         return new ZipEntryWrapper<byte[]>(next);
-      }
-   }
-   /**
-    * Write the jar contents and information
-    * @param out
-    * @throws IOException
-    */
-   private void writeObject(ObjectOutputStream out)
-      throws IOException
-   {
-      PutField fields = out.putFields();
-
-      byte[] zisBytes;
-      ZipInputStream jarStream = zis;
-      if(jarStream == null)
-      {
-         // Need to obtain this nested jar input stream from parent
-         InputStream parentIS = super.getParent().openStream();
-         if(parentIS == null)
-            throw new IOException("Failed to open parent stream, "+this);
-         jarStream = new ZipInputStream(parentIS);
-         // First find our entry
-         ZipEntry entry = jarStream.getNextEntry();
-         while(entry != null)
-         {
-            if(entry.getName().equals(getName()))
-               break;
-            entry = jarStream.getNextEntry();
-         }
-         if(entry == null)
-            throw new IOException("Failed to find nested jar entry: "+this.getName()+" in parent: "+getParent());
-      }
-      // Now read zis for this entry
-      ByteArrayOutputStream baos = new ByteArrayOutputStream();
-      byte[] tmp = new byte[1024];
-      int length = jarStream.read(tmp);
-      while(length > 0)
-      {
-         baos.write(tmp, 0, length);
-         length = jarStream.read(tmp);
-      }
-      jarStream.close();
-      jarStream = null;
-      zisBytes = baos.toByteArray();
-      fields.put("zisBytes", zisBytes);
-      fields.put("jarURL", jarURL);
-      fields.put("entryURL", entryURL);
-      fields.put("lastModified", lastModified);
-      fields.put("size", size);
-      out.writeFields();
-   }
-
-   /**
-    * Read the jar contents and reinitialize the entry map
-    * @param in
-    * @throws IOException
-    * @throws ClassNotFoundException
-    */
-   private void readObject(ObjectInputStream in)
-      throws IOException, ClassNotFoundException
-   {
-      // Read in the serialPersistentFields
-      GetField fields = in.readFields();
-      byte[] zisBytes =  (byte[]) fields.get("zisBytes", null);
-      this.jarURL = (URL) fields.get("jarURL", null);
-      this.entryURL = (URL) fields.get("entryURL", null);
-      this.lastModified = fields.get("lastModified", (long)-1);
-      this.size = fields.get("size", (long)-1);
-      // Initialize the jar entry map
-      inited = new AtomicBoolean(false);
-      ByteArrayInputStream bais = new ByteArrayInputStream(zisBytes);
-      zis = new ZipInputStream(bais);
-      this.init();
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarFromStream.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2005 Your Corporation. All Rights Reserved.
+ */
+package org.jboss.virtual.plugins.context.jar;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+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.Enumeration;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * A nested jar implementation used to represent a jar within a jar.
+ *
+ * @author Ales.Justin at jboss.org
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 44334 $
+ */
+public class NestedJarFromStream extends AbstractStructuredJarHandler<byte[]>
+{
+   /**
+    * serialVersionUID
+    */
+   private static final long serialVersionUID = 2L;
+   /** The class serial fields */
+   private static final ObjectStreamField[] serialPersistentFields = {
+      new ObjectStreamField("zisBytes", byte[].class),
+      new ObjectStreamField("jarURL", URL.class),
+      new ObjectStreamField("entryURL", String.class),
+      new ObjectStreamField("lastModified", long.class),
+      new ObjectStreamField("size", long.class)
+   };
+
+   private transient ZipInputStream zis;
+   private transient AtomicBoolean inited = new AtomicBoolean(false);
+   private URL jarURL;
+   private URL entryURL;
+   private long lastModified;
+   private long size;
+
+   /**
+    * Create a nested jar from the parent zip inputstream/zip entry.
+    *
+    * @param context   - the context containing the jar
+    * @param parent    - the jar handler for this nested jar
+    * @param zis       - the jar zip input stream
+    * @param jarURL    - the URL to use as the jar URL
+    * @param jar       - the parent jar file for the nested jar
+    * @param entry     - the zip entry
+    * @param entryName - the entry name
+    * @throws IOException for any error
+    */
+   public NestedJarFromStream(VFSContext context, VirtualFileHandler parent, ZipInputStream zis, URL jarURL, JarFile jar, ZipEntry entry, String entryName) throws IOException
+   {
+      super(context, parent, jarURL, jar, entry, entryName);
+      this.jarURL = jarURL;
+      this.lastModified = entry.getTime();
+      this.size = entry.getSize();
+      this.zis = zis;
+      try
+      {
+         setPathName(getChildPathName(entryName, false));
+         setVfsUrl(getChildVfsUrl(entryName, false));
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+   protected void initCacheLastModified()
+   {
+      cachedLastModified = lastModified;
+   }
+
+   /**
+    * Initialize entries.
+    *
+    * @throws IOException for any error
+    */
+   protected void init() throws IOException
+   {
+      if (inited.get() == false)
+      {
+         inited.set(true);
+         try
+         {
+            initJarFile(new ZisEnumeration());
+         }
+         finally
+         {
+            close();
+         }
+      }
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      init();
+      return super.getChildren(ignoreErrors);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      init();
+      return super.getChild(path);
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      init();
+      return super.createChildHandler(name);
+   }
+
+   protected void extraWrapperInfo(ZipEntryWrapper<byte[]> wrapper) throws IOException
+   {
+      byte[] contents;
+      int size = (int)wrapper.getSize();
+      if (size != 0)
+      {
+         ByteArrayOutputStream baos = size > 0 ? new ByteArrayOutputStream(size) : new ByteArrayOutputStream();
+         byte[] tmp = new byte[1024];
+         while (zis.available() > 0)
+         {
+            int length = zis.read(tmp);
+            if (length > 0)
+               baos.write(tmp, 0, length);
+         }
+         contents = baos.toByteArray();
+      }
+      else
+         contents = new byte[0];
+      wrapper.setExtra(contents);
+   }
+
+   protected VirtualFileHandler createVirtualFileHandler(VirtualFileHandler parent, ZipEntryWrapper<byte[]> wrapper, String entryName) throws IOException
+   {
+      try
+      {
+         String url = toURI().toASCIIString() + "!/" + wrapper.getName();
+         URL jecURL = new URL(url);
+         VFSContext context = parent.getVFSContext();
+         if (wrapper.isDirectory())
+         {
+            return new SynthenticDirEntryHandler(context, parent, entryName, System.currentTimeMillis(), jecURL);  
+         }
+         else
+         {
+            byte[] contents = wrapper.getExtra();
+            return new JarEntryContents(context, parent, wrapper.getEntry(), entryName, toURL(), jecURL, contents);
+         }
+      }
+      catch (Throwable t)
+      {
+         IOException ioe = new IOException("Exception while reading nested jar entry: " + this);
+         ioe.initCause(t);
+         ioe.setStackTrace(t.getStackTrace());
+         throw ioe;
+      }
+   }
+
+   /**
+    * TODO: removing the entry/jar that resulted in this needs
+    * to be detected.
+    */
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isHidden()
+   {
+      return false;
+   }
+
+   public long getSize()
+   {
+      return size;
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return lastModified;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return true;
+   }
+
+   // Stream accessor
+   public InputStream openStream() throws IOException
+   {
+      if(zis == null)
+      {
+         // Need to obtain this nested jar input stream from parent
+         InputStream parentIS = super.getParent().openStream();
+         if(parentIS == null)
+            throw new IOException("Failed to open parent stream, "+this);
+         if(parentIS instanceof ZipInputStream)
+         {
+            zis = (ZipInputStream) parentIS;
+         }
+         else
+         {
+            zis = new ZipInputStream(parentIS);
+         }
+         // First find our entry
+         ZipEntry entry = zis.getNextEntry();
+         while(entry != null)
+         {
+            if(entry.getName().equals(getName()))
+               break;
+            entry = zis.getNextEntry();
+         }
+         if(entry == null)
+            throw new IOException("Failed to find nested jar entry: "+this.getName()+" in parent: "+getParent());
+      }
+      return zis;
+   }
+
+   public void close()
+   {
+      if (zis != null)
+      {
+         try
+         {
+            zis.close();
+         }
+         catch (IOException e)
+         {
+            log.error("close error", e);
+         }
+         zis = null;
+      }
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      try
+      {
+         if (entryURL == null)
+            entryURL = new URL(jarURL, getName());
+      }
+      catch (MalformedURLException e)
+      {
+         throw new URISyntaxException("Failed to create relative jarURL", e.getMessage());
+      }
+      return entryURL.toURI();
+   }
+
+   public String toString()
+   {
+      StringBuffer tmp = new StringBuffer(super.toString());
+      tmp.append('[');
+      tmp.append("name=");
+      tmp.append(getName());
+      tmp.append(",size=");
+      tmp.append(getSize());
+      tmp.append(",lastModified=");
+      tmp.append(lastModified);
+      tmp.append(",URI=");
+      try
+      {
+         tmp.append(toURI());
+      }
+      catch (URISyntaxException e)
+      {
+      }
+      tmp.append(']');
+      return tmp.toString();
+   }
+
+   protected void initJarFile() throws IOException
+   {
+      // todo - deserialize
+   }
+
+   private class ZisEnumeration implements Enumeration<ZipEntryWrapper<byte[]>>
+   {
+      private boolean moved = true;
+      private ZipEntry next = null;
+
+      public boolean hasMoreElements()
+      {
+         if (zis == null)
+            return false;
+         
+         try
+         {
+            if (moved)
+            {
+               next = zis.getNextEntry();
+               moved = false;
+            }
+            return next != null;
+         }
+         catch (IOException e)
+         {
+            throw new RuntimeException(e);
+         }
+      }
+
+      public ZipEntryWrapper<byte[]> nextElement()
+      {
+         moved = true;
+         return new ZipEntryWrapper<byte[]>(next);
+      }
+   }
+   /**
+    * Write the jar contents and information
+    * @param out
+    * @throws IOException
+    */
+   private void writeObject(ObjectOutputStream out)
+      throws IOException
+   {
+      PutField fields = out.putFields();
+
+      byte[] zisBytes;
+      ZipInputStream jarStream = zis;
+      if(jarStream == null)
+      {
+         // Need to obtain this nested jar input stream from parent
+         InputStream parentIS = super.getParent().openStream();
+         if(parentIS == null)
+            throw new IOException("Failed to open parent stream, "+this);
+         jarStream = new ZipInputStream(parentIS);
+         // First find our entry
+         ZipEntry entry = jarStream.getNextEntry();
+         while(entry != null)
+         {
+            if(entry.getName().equals(getName()))
+               break;
+            entry = jarStream.getNextEntry();
+         }
+         if(entry == null)
+            throw new IOException("Failed to find nested jar entry: "+this.getName()+" in parent: "+getParent());
+      }
+      // Now read zis for this entry
+      ByteArrayOutputStream baos = new ByteArrayOutputStream();
+      byte[] tmp = new byte[1024];
+      int length = jarStream.read(tmp);
+      while(length > 0)
+      {
+         baos.write(tmp, 0, length);
+         length = jarStream.read(tmp);
+      }
+      jarStream.close();
+      jarStream = null;
+      zisBytes = baos.toByteArray();
+      fields.put("zisBytes", zisBytes);
+      fields.put("jarURL", jarURL);
+      fields.put("entryURL", entryURL);
+      fields.put("lastModified", lastModified);
+      fields.put("size", size);
+      out.writeFields();
+   }
+
+   /**
+    * Read the jar contents and reinitialize the entry map
+    * @param in
+    * @throws IOException
+    * @throws ClassNotFoundException
+    */
+   private void readObject(ObjectInputStream in)
+      throws IOException, ClassNotFoundException
+   {
+      // Read in the serialPersistentFields
+      GetField fields = in.readFields();
+      byte[] zisBytes =  (byte[]) fields.get("zisBytes", null);
+      this.jarURL = (URL) fields.get("jarURL", null);
+      this.entryURL = (URL) fields.get("entryURL", null);
+      this.lastModified = fields.get("lastModified", (long)-1);
+      this.size = fields.get("size", (long)-1);
+      // Initialize the jar entry map
+      inited = new AtomicBoolean(false);
+      ByteArrayInputStream bais = new ByteArrayInputStream(zisBytes);
+      zis = new ZipInputStream(bais);
+      this.init();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,192 +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.jar;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * Nested Jar Handler.
- * 
- * @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
- * @version $Revision: 1.1 $
- */
-public class NestedJarHandler extends AbstractStructuredJarHandler<Object>
-{
-   /** serialVersionUID */
-   private static final long serialVersionUID = 1L;
-
-   /** The temporary file */
-   private transient File temp;
-
-   /**
-    * Create a temporary jar
-    * 
-    * @param temp the temporary file
-    * @param parentJar the jar
-    * @param entry the jar entry
-    * @return the jar file
-    * @throws IOException for any error
-    */
-   private static JarFile createTempJar(File temp, JarFile parentJar, ZipEntry entry) throws IOException
-   {
-      InputStream inputStream = parentJar.getInputStream(entry);
-      try
-      {
-         FileOutputStream outputStream = new FileOutputStream(temp);
-         try
-         {
-            byte[] buffer = new byte[8096];
-            int read = inputStream.read(buffer);
-            while (read != -1)
-            {
-               outputStream.write(buffer, 0, read);
-               read = inputStream.read(buffer);
-            }
-         }
-         finally
-         {
-            outputStream.close();
-         }
-      }
-      finally
-      {
-         try
-         {
-            inputStream.close();
-         }
-         catch (IOException ignored)
-         {
-         }
-      }
-      
-      return new JarFile(temp);
-   }
-
-   public static NestedJarHandler create(VFSContext context, VirtualFileHandler parent,
-         JarFile parentJar, ZipEntry entry, URL url, String entryName) throws IOException
-   {
-      File temp;
-      try
-      {
-         temp = File.createTempFile("nestedjar", null);
-         temp.deleteOnExit();
-      }
-      catch (IOException original)
-      {
-         // Fix the context of the error message
-         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
-         e.setStackTrace(original.getStackTrace());
-         throw e;
-      }
-      return new NestedJarHandler(context, parent, parentJar, entry, url, temp, entryName);
-   }
-
-   /**
-    * Create a new NestedJarHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param parentJar the parent jar file
-    * @param entry the jar entry
-    * @param original the original url
-    * @param temp the temporary file
-    * @param entryName the entry name
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url or vfsPath
-    */
-   protected NestedJarHandler(VFSContext context, VirtualFileHandler parent, JarFile parentJar, ZipEntry entry, URL original, File temp, String entryName)
-      throws IOException
-   {
-      super(context, parent, temp.toURL(), createTempJar(temp, parentJar, entry), entry, entryName);
-
-      try
-      {
-         setPathName(getChildPathName(entryName, false));
-         setVfsUrl(getChildVfsUrl(entryName, false));
-      }
-      catch (URISyntaxException e)
-      {
-         throw new RuntimeException(e);
-      }
-
-      this.temp = temp;
-
-      try
-      {
-         initJarFile();
-      }
-      catch (IOException old)
-      {
-         // Fix the context of the error message
-         IOException e = new IOException("Error opening jar file: " + original + " reason=" + old.getMessage());
-         e.setStackTrace(old.getStackTrace());
-         throw e;
-      }
-   }
-
-   @Override
-   public long getLastModified() throws IOException
-   {
-      return getEntry().getTime();
-   }
-
-   @Override
-   public long getSize() throws IOException
-   {
-      return getEntry().getSize();
-   }
-
-   /**
-    * Overriden to return the raw tmp jar file stream 
-    */
-   @Override
-   public InputStream openStream() throws IOException
-   {
-      return new FileInputStream(temp);
-   }
-
-   /**
-    * Restore the temp file
-    *
-    * @param in the input stream
-    * @throws IOException for any error reading the jar file
-    * @throws ClassNotFoundException for any jar class finding errors
-    */
-   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
-   {
-      // TODO - temp?
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,197 @@
+/*
+* 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.jar;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * Nested Jar Handler.
+ * 
+ * @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
+ * @version $Revision: 1.1 $
+ */
+public class NestedJarHandler extends AbstractStructuredJarHandler<Object>
+{
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+
+   /** The temporary file */
+   private transient File temp;
+
+   /**
+    * Create a temporary jar
+    * 
+    * @param temp the temporary file
+    * @param parentJar the jar
+    * @param entry the jar entry
+    * @return the jar file
+    * @throws IOException for any error
+    */
+   private static JarFile createTempJar(File temp, JarFile parentJar, ZipEntry entry) throws IOException
+   {
+      InputStream inputStream = parentJar.getInputStream(entry);
+      try
+      {
+         FileOutputStream outputStream = new FileOutputStream(temp);
+         try
+         {
+            byte[] buffer = new byte[8096];
+            int read = inputStream.read(buffer);
+            while (read != -1)
+            {
+               outputStream.write(buffer, 0, read);
+               read = inputStream.read(buffer);
+            }
+         }
+         finally
+         {
+            outputStream.close();
+         }
+      }
+      finally
+      {
+         try
+         {
+            inputStream.close();
+         }
+         catch (IOException ignored)
+         {
+         }
+      }
+      
+      return new JarFile(temp);
+   }
+
+   public static NestedJarHandler create(VFSContext context, VirtualFileHandler parent,
+         JarFile parentJar, ZipEntry entry, URL url, String entryName) throws IOException
+   {
+      File temp;
+      try
+      {
+         temp = File.createTempFile("nestedjar", null);
+         temp.deleteOnExit();
+      }
+      catch (IOException original)
+      {
+         // Fix the context of the error message
+         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
+         e.setStackTrace(original.getStackTrace());
+         throw e;
+      }
+      return new NestedJarHandler(context, parent, parentJar, entry, url, temp, entryName);
+   }
+
+   /**
+    * Create a new NestedJarHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param parentJar the parent jar file
+    * @param entry the jar entry
+    * @param original the original url
+    * @param temp the temporary file
+    * @param entryName the entry name
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url or vfsPath
+    */
+   protected NestedJarHandler(VFSContext context, VirtualFileHandler parent, JarFile parentJar, ZipEntry entry, URL original, File temp, String entryName)
+      throws IOException
+   {
+      super(context, parent, temp.toURL(), createTempJar(temp, parentJar, entry), entry, entryName);
+
+      try
+      {
+         setPathName(getChildPathName(entryName, false));
+         setVfsUrl(getChildVfsUrl(entryName, false));
+      }
+      catch (URISyntaxException e)
+      {
+         throw new RuntimeException(e);
+      }
+
+      this.temp = temp;
+
+      try
+      {
+         initJarFile();
+      }
+      catch (IOException old)
+      {
+         // Fix the context of the error message
+         IOException e = new IOException("Error opening jar file: " + original + " reason=" + old.getMessage());
+         e.setStackTrace(old.getStackTrace());
+         throw e;
+      }
+   }
+
+   @Override
+   public long getLastModified() throws IOException
+   {
+      return getEntry().getTime();
+   }
+
+   @Override
+   public long getSize() throws IOException
+   {
+      return getEntry().getSize();
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   /**
+    * Overriden to return the raw tmp jar file stream 
+    */
+   @Override
+   public InputStream openStream() throws IOException
+   {
+      return new FileInputStream(temp);
+   }
+
+   /**
+    * Restore the temp file
+    *
+    * @param in the input stream
+    * @throws IOException for any error reading the jar file
+    * @throws ClassNotFoundException for any jar class finding errors
+    */
+   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+   {
+      // TODO - temp?
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,142 +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.jar;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.List;
-import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * Nested Jar Handler.
- * 
- * @author <a href="ales.justin at jboss.org">Ales Justin</a>
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class NoCopyNestedJarHandler extends AbstractJarHandler
-{
-   /** serialVersionUID */
-   private static final long serialVersionUID = 1L;
-
-   /** The nested jar */
-   private NestedJarFromStream njar;
-
-   /**
-    * Create a new NestedJarHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param parentJar the parent jar file
-    * @param entry the jar entry
-    * @param url the url
-    * @param entryName the entry name
-    * @throws IOException for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url or vfsPath
-    */
-   public NoCopyNestedJarHandler(VFSContext context, VirtualFileHandler parent, JarFile parentJar, ZipEntry entry, URL url, String entryName) throws IOException
-   {
-      super(context, parent, url, parentJar, entry, entryName);
-      
-      try
-      {
-         setPathName(getChildPathName(entryName, false));
-         setVfsUrl(getChildVfsUrl(entryName, false));
-      }
-      catch (URISyntaxException e)
-      {
-         throw new RuntimeException(e);
-      }
-
-      try
-      {
-         InputStream is = parentJar.getInputStream(entry);
-         ZipInputStream zis;
-         if(is instanceof ZipInputStream)
-         {
-            zis = (ZipInputStream) is;
-         }
-         else
-         {
-            zis = new ZipInputStream(is);
-         }
-         njar = new NestedJarFromStream(context, parent, zis, url, parentJar, entry, entryName);
-      }
-      catch (IOException original)
-      {
-         // Fix the context of the error message
-         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
-         e.setStackTrace(original.getStackTrace());
-         throw e;
-      }
-   }
-   
-   protected void initCacheLastModified()
-   {
-   }
-
-   @Override
-   public long getLastModified() throws IOException
-   {
-      return getEntry().getTime();
-   }
-
-   @Override
-   public long getSize() throws IOException
-   {
-      return getEntry().getSize();
-   }
-
-   @Override
-   public InputStream openStream() throws IOException
-   {
-      return getJar().getInputStream(getEntry());
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      if (path == null)
-         throw new IllegalArgumentException("Null path");
-
-      if ("".equals(path))
-         return this;
-
-      return njar.getChild(path);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return njar.getChildren(ignoreErrors);
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      njar.internalReplaceChild(original, replacement);
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/NoCopyNestedJarHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,147 @@
+/*
+* 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.jar;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * Nested Jar Handler.
+ * 
+ * @author <a href="ales.justin at jboss.org">Ales Justin</a>
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class NoCopyNestedJarHandler extends AbstractJarHandler
+{
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+
+   /** The nested jar */
+   private NestedJarFromStream njar;
+
+   /**
+    * Create a new NestedJarHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param parentJar the parent jar file
+    * @param entry the jar entry
+    * @param url the url
+    * @param entryName the entry name
+    * @throws IOException for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url or vfsPath
+    */
+   public NoCopyNestedJarHandler(VFSContext context, VirtualFileHandler parent, JarFile parentJar, ZipEntry entry, URL url, String entryName) throws IOException
+   {
+      super(context, parent, url, parentJar, entry, entryName);
+      
+      try
+      {
+         setPathName(getChildPathName(entryName, false));
+         setVfsUrl(getChildVfsUrl(entryName, false));
+      }
+      catch (URISyntaxException e)
+      {
+         throw new RuntimeException(e);
+      }
+
+      try
+      {
+         InputStream is = parentJar.getInputStream(entry);
+         ZipInputStream zis;
+         if(is instanceof ZipInputStream)
+         {
+            zis = (ZipInputStream) is;
+         }
+         else
+         {
+            zis = new ZipInputStream(is);
+         }
+         njar = new NestedJarFromStream(context, parent, zis, url, parentJar, entry, entryName);
+      }
+      catch (IOException original)
+      {
+         // Fix the context of the error message
+         IOException e = new IOException("Error opening jar file: " + url + " reason=" + original.getMessage());
+         e.setStackTrace(original.getStackTrace());
+         throw e;
+      }
+   }
+   
+   protected void initCacheLastModified()
+   {
+   }
+
+   @Override
+   public long getLastModified() throws IOException
+   {
+      return getEntry().getTime();
+   }
+
+   @Override
+   public long getSize() throws IOException
+   {
+      return getEntry().getSize();
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return true;
+   }
+
+   @Override
+   public InputStream openStream() throws IOException
+   {
+      return getJar().getInputStream(getEntry());
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      if (path == null)
+         throw new IllegalArgumentException("Null path");
+
+      if ("".equals(path))
+         return this;
+
+      return njar.getChild(path);
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return njar.getChildren(ignoreErrors);
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      njar.internalReplaceChild(original, replacement);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,189 +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.jar;
-
-import java.io.IOException;
-import java.io.InputStream;
-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.virtual.plugins.context.AbstractURLHandler;
-import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * SynthenticDirEntryHandler represents non-existent directory jar entry.
- *
- * @author Scott.Stark at jboss.org
- * @version $Revision: 1.1 $
- */
-public class SynthenticDirEntryHandler extends AbstractURLHandler
-      implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
-{
-   /**
-    * serialVersionUID
-    */
-   private static final long serialVersionUID = 1L;
-
-   /**
-    * The jar file
-    */
-   private List<VirtualFileHandler> entryChildren;
-   private transient Map<String, VirtualFileHandler> entryMap;
-
-   /**
-    * Create a new SynthenticDirEntryHandler.
-    *
-    * @param context      the context
-    * @param parent       the parent
-    * @param entryName    - the simple name for the dir
-    * @param lastModified the timestamp for the dir
-    * @param url          the full url
-    * @throws IOException              for an error accessing the file system
-    * @throws IllegalArgumentException for a null context, url, jar or entry
-    */
-   public SynthenticDirEntryHandler(VFSContext context, VirtualFileHandler parent,
-                                    String entryName, long lastModified, URL url)
-         throws IOException
-   {
-      super(context, parent, url, entryName);
-      try
-      {
-         URL parentVfsUrl = parent.toVfsUrl();
-         String vfsParentUrl = parentVfsUrl.toString();
-         setVfsUrl(getChildVfsUrl(entryName, vfsParentUrl.endsWith("/") == false));
-      }
-      catch (URISyntaxException e)
-      {
-         throw new RuntimeException(e);
-      }
-      this.cachedLastModified = lastModified;
-   }
-
-   protected void initCacheLastModified()
-   {
-   }
-
-   /**
-    * Add a child to an entry
-    *
-    * @param child the child file handler
-    */
-   public synchronized void addChild(VirtualFileHandler child)
-   {
-      if (entryChildren == null)
-         entryChildren = new ArrayList<VirtualFileHandler>();
-      entryChildren.add(child);
-      if (entryMap != null)
-         entryMap.put(child.getName(), child);
-   }
-
-   @Override
-   public long getLastModified() throws IOException
-   {
-      checkParentExists();
-      return getParent().getLastModified();
-   }
-
-   @Override
-   public long getSize()
-   {
-      return 0;
-   }
-
-   /**
-    * TODO: removing the entry/jar that resulted in this needs
-    * to be detected.
-    */
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isLeaf()
-   {
-      return false;
-   }
-
-   public boolean isHidden()
-   {
-      checkClosed();
-      return false;
-   }
-
-   @Override
-   public InputStream openStream() throws IOException
-   {
-      throw new IOException("Directories cannot be opened");
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      checkClosed();
-      if (entryChildren == null)
-         return Collections.emptyList();
-      return Collections.unmodifiableList(entryChildren);
-   }
-
-   /**
-    * Create a child handler for the given name. This looks to the entryMap
-    * for an existing child.
-    *
-    * @param name - the simple name of an immeadiate child.
-    * @return the VirtualFileHandler previously added via addChild.
-    * @throws IOException - thrown if there are no children or the
-    *                     name does not match a child
-    */
-   // TODO: synchronization on lazy entryMap creation
-   public synchronized VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      if (entryChildren == null)
-         return null;
-
-      if (entryMap == null)
-      {
-         entryMap = new HashMap<String, VirtualFileHandler>();
-         for (VirtualFileHandler child : entryChildren)
-            entryMap.put(child.getName(), child);
-      }
-      return entryMap.get(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      entryChildren.remove(original);
-      entryChildren.add(replacement);
-      entryMap.put(original.getName(), replacement);
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,194 @@
+/*
+* 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.jar;
+
+import java.io.IOException;
+import java.io.InputStream;
+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.virtual.plugins.context.AbstractURLHandler;
+import org.jboss.virtual.plugins.context.HierarchyVirtualFileHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * SynthenticDirEntryHandler represents non-existent directory jar entry.
+ *
+ * @author Scott.Stark at jboss.org
+ * @version $Revision: 1.1 $
+ */
+public class SynthenticDirEntryHandler extends AbstractURLHandler
+      implements StructuredVirtualFileHandler, HierarchyVirtualFileHandler
+{
+   /**
+    * serialVersionUID
+    */
+   private static final long serialVersionUID = 1L;
+
+   /**
+    * The jar file
+    */
+   private List<VirtualFileHandler> entryChildren;
+   private transient Map<String, VirtualFileHandler> entryMap;
+
+   /**
+    * Create a new SynthenticDirEntryHandler.
+    *
+    * @param context      the context
+    * @param parent       the parent
+    * @param entryName    - the simple name for the dir
+    * @param lastModified the timestamp for the dir
+    * @param url          the full url
+    * @throws IOException              for an error accessing the file system
+    * @throws IllegalArgumentException for a null context, url, jar or entry
+    */
+   public SynthenticDirEntryHandler(VFSContext context, VirtualFileHandler parent,
+                                    String entryName, long lastModified, URL url)
+         throws IOException
+   {
+      super(context, parent, url, entryName);
+      try
+      {
+         URL parentVfsUrl = parent.toVfsUrl();
+         String vfsParentUrl = parentVfsUrl.toString();
+         setVfsUrl(getChildVfsUrl(entryName, vfsParentUrl.endsWith("/") == false));
+      }
+      catch (URISyntaxException e)
+      {
+         throw new RuntimeException(e);
+      }
+      this.cachedLastModified = lastModified;
+   }
+
+   protected void initCacheLastModified()
+   {
+   }
+
+   /**
+    * Add a child to an entry
+    *
+    * @param child the child file handler
+    */
+   public synchronized void addChild(VirtualFileHandler child)
+   {
+      if (entryChildren == null)
+         entryChildren = new ArrayList<VirtualFileHandler>();
+      entryChildren.add(child);
+      if (entryMap != null)
+         entryMap.put(child.getName(), child);
+   }
+
+   @Override
+   public long getLastModified() throws IOException
+   {
+      checkParentExists();
+      return getParent().getLastModified();
+   }
+
+   @Override
+   public long getSize()
+   {
+      return 0;
+   }
+
+   /**
+    * TODO: removing the entry/jar that resulted in this needs
+    * to be detected.
+    */
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isLeaf()
+   {
+      return false;
+   }
+
+   public boolean isHidden()
+   {
+      checkClosed();
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return true;
+   }
+
+   @Override
+   public InputStream openStream() throws IOException
+   {
+      throw new IOException("Directories cannot be opened");
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      checkClosed();
+      if (entryChildren == null)
+         return Collections.emptyList();
+      return Collections.unmodifiableList(entryChildren);
+   }
+
+   /**
+    * Create a child handler for the given name. This looks to the entryMap
+    * for an existing child.
+    *
+    * @param name - the simple name of an immeadiate child.
+    * @return the VirtualFileHandler previously added via addChild.
+    * @throws IOException - thrown if there are no children or the
+    *                     name does not match a child
+    */
+   // TODO: synchronization on lazy entryMap creation
+   public synchronized VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      if (entryChildren == null)
+         return null;
+
+      if (entryMap == null)
+      {
+         entryMap = new HashMap<String, VirtualFileHandler>();
+         for (VirtualFileHandler child : entryChildren)
+            entryMap.put(child.getName(), child);
+      }
+      return entryMap.get(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      entryChildren.remove(original);
+      entryChildren.add(replacement);
+      entryMap.put(original.getName(), replacement);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,179 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source.
-* Copyright 2006, Red Hat Middleware LLC, and individual contributors
-* as indicated by the @author tags. See the copyright.txt file 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.memory;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.virtual.plugins.context.AbstractURLHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-
-/**
- * Virtual memory context handler.
- *
- * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
- * @version $Revision: 1.1 $
- */
-public class MemoryContextHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
-{
-   /** serialVersionUID */
-   private static final long serialVersionUID = 1L;
-   /** The entries */
-   private Map<String, MemoryContextHandler> entryMap = Collections.emptyMap();
-   /** The content */
-   private byte[] contents;
-
-   public MemoryContextHandler(VFSContext context, VirtualFileHandler parent, URL url, String name)
-   {
-      super(context, parent, url, name);
-      if (parent != null && parent instanceof MemoryContextHandler)
-      {
-         ((MemoryContextHandler)parent).addChild(name, this);
-      }
-   }
-
-   protected synchronized void addChild(String name, MemoryContextHandler child)
-   {
-      if (entryMap == Collections.EMPTY_MAP)
-      {
-         entryMap = new LinkedHashMap<String, MemoryContextHandler>();
-      }
-      entryMap.put(name, child);
-   }
-   
-   boolean deleteChild(MemoryContextHandler child)
-   {
-      return entryMap.remove(child.getName()) != null;
-   }
-   
-   MemoryContextHandler getDirectChild(String name)
-   {
-      return entryMap.get(name);
-   }
-   
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return new ArrayList<VirtualFileHandler>(entryMap.values());
-   }
-
-   public boolean isLeaf()
-   {
-      return contents != null;
-   }
-
-   /**
-    * Called by structuredFindChild
-    */
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      return entryMap.get(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   @Override
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-   
-   byte[] getContents()
-   {
-      return contents;
-   }
-
-   public void setContents(byte[] contents)
-   {
-      if (entryMap.size() > 0)
-      {
-         throw new RuntimeException("Cannot set contents for non-leaf node");
-      }
-      initCacheLastModified();
-      this.contents = contents;
-   }
-   
-   @Override
-   protected void initCacheLastModified()
-   {
-      this.cachedLastModified = System.currentTimeMillis();
-   }
-
-   @Override
-   public long getSize() throws IOException
-   {
-      if (contents != null)
-      {
-         return contents.length;
-      }
-      return 0;
-   }
-   
-   @Override
-   public long getLastModified() throws IOException
-   {
-      return cachedLastModified;
-   }
-
-   @Override
-   public InputStream openStream() throws IOException
-   {
-      if (contents != null)
-      {
-         return new ByteArrayInputStream(contents);
-      }
-      return new ByteArrayInputStream(new byte[0]);
-   }
-
-   @Override
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      if (getVfsUrl() == null)
-      {
-         if (isLeaf())
-         {
-            setVfsUrl(getURL());
-         }
-         else
-         {
-            String vfsString = getURL().toString(); 
-            if (vfsString.endsWith("/") == false)
-               setVfsUrl(new URL(vfsString + "/"));
-         }
-      }
-      return getVfsUrl();
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,184 @@
+/*
+* JBoss, Home of Professional Open Source.
+* Copyright 2006, Red Hat Middleware LLC, and individual contributors
+* as indicated by the @author tags. See the copyright.txt file 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.memory;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.virtual.plugins.context.AbstractURLHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+
+/**
+ * Virtual memory context handler.
+ *
+ * @author <a href="kabir.khan at jboss.com">Kabir Khan</a>
+ * @version $Revision: 1.1 $
+ */
+public class MemoryContextHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
+{
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+   /** The entries */
+   private Map<String, MemoryContextHandler> entryMap = Collections.emptyMap();
+   /** The content */
+   private byte[] contents;
+
+   public MemoryContextHandler(VFSContext context, VirtualFileHandler parent, URL url, String name)
+   {
+      super(context, parent, url, name);
+      if (parent != null && parent instanceof MemoryContextHandler)
+      {
+         ((MemoryContextHandler)parent).addChild(name, this);
+      }
+   }
+
+   protected synchronized void addChild(String name, MemoryContextHandler child)
+   {
+      if (entryMap == Collections.EMPTY_MAP)
+      {
+         entryMap = new LinkedHashMap<String, MemoryContextHandler>();
+      }
+      entryMap.put(name, child);
+   }
+   
+   boolean deleteChild(MemoryContextHandler child)
+   {
+      return entryMap.remove(child.getName()) != null;
+   }
+   
+   MemoryContextHandler getDirectChild(String name)
+   {
+      return entryMap.get(name);
+   }
+   
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return new ArrayList<VirtualFileHandler>(entryMap.values());
+   }
+
+   public boolean isLeaf()
+   {
+      return contents != null;
+   }
+
+   /**
+    * Called by structuredFindChild
+    */
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      return entryMap.get(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   @Override
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+   
+   byte[] getContents()
+   {
+      return contents;
+   }
+
+   public void setContents(byte[] contents)
+   {
+      if (entryMap.size() > 0)
+      {
+         throw new RuntimeException("Cannot set contents for non-leaf node");
+      }
+      initCacheLastModified();
+      this.contents = contents;
+   }
+   
+   @Override
+   protected void initCacheLastModified()
+   {
+      this.cachedLastModified = System.currentTimeMillis();
+   }
+
+   @Override
+   public long getSize() throws IOException
+   {
+      if (contents != null)
+      {
+         return contents.length;
+      }
+      return 0;
+   }
+   
+   @Override
+   public long getLastModified() throws IOException
+   {
+      return cachedLastModified;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   @Override
+   public InputStream openStream() throws IOException
+   {
+      if (contents != null)
+      {
+         return new ByteArrayInputStream(contents);
+      }
+      return new ByteArrayInputStream(new byte[0]);
+   }
+
+   @Override
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      if (getVfsUrl() == null)
+      {
+         if (isLeaf())
+         {
+            setVfsUrl(getURL());
+         }
+         else
+         {
+            String vfsString = getURL().toString(); 
+            if (vfsString.endsWith("/") == false)
+               setVfsUrl(new URL(vfsString + "/"));
+         }
+      }
+      return getVfsUrl();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,158 +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.vfs;
-
-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.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.AssembledDirectory;
-import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * The assembled directory handler.
- *
- * @author <a href="bill at jboss.com">Bill Burke</a>
- * @version $Revision: 1.1 $
- */
- at Assembled
-public class AssembledDirectoryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
-{
-   private long lastModified = System.currentTimeMillis();
-   private List<VirtualFileHandler> children = new ArrayList<VirtualFileHandler>();
-   private Map<String, VirtualFileHandler> childrenMap = new HashMap<String, VirtualFileHandler>();
-
-   public AssembledDirectoryHandler(VFSContext context, AssembledDirectoryHandler parent, String name) throws IOException
-   {
-      super(context, parent, name);
-      String path = getPathName();
-      if (path.endsWith("/") == false)
-         path += "/";
-      setVfsUrl(new URL("vfs", context.getName(), -1, path, new AssembledUrlStreamHandler(context)));
-   }
-
-   public VirtualFileHandler addChild(VirtualFileHandler handler)
-   {
-      if (handler.getClass().isAnnotationPresent(Assembled.class) == false)
-      {
-         try
-         {
-            handler = new AssembledFileHandler(getVFSContext(), this, handler.getName(), handler);
-         }
-         catch (IOException e)
-         {
-            throw new RuntimeException(e);
-         }
-      }
-      children.add(handler);
-      childrenMap.put(handler.getName(), handler);
-      lastModified = System.currentTimeMillis();
-      return handler;
-   }
-
-   public VirtualFileHandler findChild(String name)
-   {
-      return childrenMap.get(name);
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return getVfsUrl().toURI();
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return lastModified;
-   }
-
-   public long getSize() throws IOException
-   {
-      return 0;
-   }
-
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      return false;
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      return false;
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      throw new RuntimeException("Cannot open stream");
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return children;
-   }
-
-   public VirtualFileHandler createChildHandler(String name) throws IOException
-   {
-      return childrenMap.get(name);
-   }
-
-   @Override
-   public VirtualFile getVirtualFile()
-   {
-      checkClosed();
-      increment();
-      return new AssembledDirectory(this);
-   }
-
-   @Override
-   public URL toURL() throws MalformedURLException, URISyntaxException
-   {
-      return getVfsUrl();
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      children.remove(original);
-      children.add(replacement);
-      childrenMap.put(original.getName(), replacement);
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/AssembledDirectoryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,163 @@
+/*
+* 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.vfs;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.AssembledDirectory;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * The assembled directory handler.
+ *
+ * @author <a href="bill at jboss.com">Bill Burke</a>
+ * @version $Revision: 1.1 $
+ */
+ at Assembled
+public class AssembledDirectoryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
+{
+   private long lastModified = System.currentTimeMillis();
+   private List<VirtualFileHandler> children = new ArrayList<VirtualFileHandler>();
+   private Map<String, VirtualFileHandler> childrenMap = new HashMap<String, VirtualFileHandler>();
+
+   public AssembledDirectoryHandler(VFSContext context, AssembledDirectoryHandler parent, String name) throws IOException
+   {
+      super(context, parent, name);
+      String path = getPathName();
+      if (path.endsWith("/") == false)
+         path += "/";
+      setVfsUrl(new URL("vfs", context.getName(), -1, path, new AssembledUrlStreamHandler(context)));
+   }
+
+   public VirtualFileHandler addChild(VirtualFileHandler handler)
+   {
+      if (handler.getClass().isAnnotationPresent(Assembled.class) == false)
+      {
+         try
+         {
+            handler = new AssembledFileHandler(getVFSContext(), this, handler.getName(), handler);
+         }
+         catch (IOException e)
+         {
+            throw new RuntimeException(e);
+         }
+      }
+      children.add(handler);
+      childrenMap.put(handler.getName(), handler);
+      lastModified = System.currentTimeMillis();
+      return handler;
+   }
+
+   public VirtualFileHandler findChild(String name)
+   {
+      return childrenMap.get(name);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return getVfsUrl().toURI();
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return lastModified;
+   }
+
+   public long getSize() throws IOException
+   {
+      return 0;
+   }
+
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      return false;
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      throw new RuntimeException("Cannot open stream");
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      return children;
+   }
+
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      return childrenMap.get(name);
+   }
+
+   @Override
+   public VirtualFile getVirtualFile()
+   {
+      checkClosed();
+      increment();
+      return new AssembledDirectory(this);
+   }
+
+   @Override
+   public URL toURL() throws MalformedURLException, URISyntaxException
+   {
+      return getVfsUrl();
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      children.remove(original);
+      children.add(replacement);
+      childrenMap.put(original.getName(), replacement);
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,108 +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.vfs;
-
-import java.io.ByteArrayInputStream;
-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.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * comment
- *
- * @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 Assembled
-public class ByteArrayHandler extends AbstractVirtualFileHandler
-{
-   private byte[] bytes;
-   private final long lastModified;
-
-   public ByteArrayHandler(VFSContext context, VirtualFileHandler parent, String name, byte[] bytes) throws IOException
-   {
-      super(context, parent, name);
-      this.bytes = bytes;
-      lastModified = System.currentTimeMillis();
-      setVfsUrl(new URL("vfs", context.getName(), -1, getPathName(), new AssembledUrlStreamHandler(context)));
-   }
-
-   @Override
-   public URL toURL() throws MalformedURLException, URISyntaxException
-   {
-      return getVfsUrl();
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return getVfsUrl().toURI();
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return lastModified;
-   }
-
-   public long getSize() throws IOException
-   {
-      return bytes.length;
-   }
-
-   public boolean exists() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      return true;
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      return false;
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      return new ByteArrayInputStream(bytes);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      throw new IOException("File cannot have children");
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      throw new IOException("File cannot have children");
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/vfs/ByteArrayHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,113 @@
+/*
+* 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.vfs;
+
+import java.io.ByteArrayInputStream;
+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.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * ByteArrayHandler.
+ *
+ * @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 Assembled
+public class ByteArrayHandler extends AbstractVirtualFileHandler
+{
+   private byte[] bytes;
+   private final long lastModified;
+
+   public ByteArrayHandler(VFSContext context, VirtualFileHandler parent, String name, byte[] bytes) throws IOException
+   {
+      super(context, parent, name);
+      this.bytes = bytes;
+      lastModified = System.currentTimeMillis();
+      setVfsUrl(new URL("vfs", context.getName(), -1, getPathName(), new AssembledUrlStreamHandler(context)));
+   }
+
+   @Override
+   public URL toURL() throws MalformedURLException, URISyntaxException
+   {
+      return getVfsUrl();
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return getVfsUrl().toURI();
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return lastModified;
+   }
+
+   public long getSize() throws IOException
+   {
+      return bytes.length;
+   }
+
+   public boolean exists() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      return true;
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return false;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return false;
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      return new ByteArrayInputStream(bytes);
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      throw new IOException("File cannot have children");
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      throw new IOException("File cannot have children");
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,934 +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.File;
-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 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.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>ZipStremWrapper</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>.
- *
- * 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
-{
-   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 ConcurrentHashMap<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
-
-
-   /**
-    * Create a new ZipEntryContext
-    *
-    * @param rootURL - file or jar:file url
-    * @throws URISyntaxException
-    * @throws IOException
-    */
-   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
-    * @throws java.io.IOException
-    */
-   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
-    * @throws java.io.IOException
-    */
-   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
-    * @throws IOException
-    */
-   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
-    * @throws IOException
-    */
-   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 that couldn't fit inside constructors
-    *
-    * @param localRootURL
-    * @param peer
-    * @param zipWrapper
-    * @throws IOException
-    * @throws URISyntaxException
-    */
-   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);
-
-         String noReaper = getOptions().get(VFSUtils.NO_REAPER_QUERY);
-         zipSource = new ZipFileWrapper(VFSUtils.toURI(new URL(rootPath)), autoClean, Boolean.valueOf(noReaper));
-      }
-      else
-      {
-         zipSource = zipWrapper;
-      }
-      
-      setRootPeer(peer);
-
-      String name = getRootURI().toString();
-      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));
-
-      initEntries();
-      ZipEntryContextFactory.registerContext(this);
-   }
-
-   /**
-    * 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 IOException
-    * @throws URISyntaxException
-    */
-   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
-
-      HashMap<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);
-            }
-         }
-
-         TreeMap<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 = 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));
-                  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();
-      }
-
-   }
-
-   /**
-    * Mount ZipEntryContext created around extracted nested archive
-    *
-    * @param parent
-    * @param name
-    * @param file
-    * @return
-    * @throws IOException
-    * @throws URISyntaxException
-    */
-   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);
-
-      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl, true);
-      VirtualFileHandler handler = ctx.getRoot();
-      delegator.setDelegate(handler);
-
-      return delegator;
-   }
-
-   /**
-    * Mount ZipEntryContext created around ZipStreamWrapper
-    *
-    * @param parent
-    * @param name
-    * @param zipStream
-    * @return
-    * @throws IOException
-    * @throws URISyntaxException
-    */
-   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);
-
-      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
-    * @return
-    * @throws IOException
-    */
-   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
-    * @return
-    */
-   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 "file:" + filePath;
-   }
-
-   /**
-    * If archive has been modified, clear <em>entries</em> and re-initialize
-    */
-   private synchronized void checkIfModified()
-   {
-      // TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
-      if (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);
-            }
-         }
-      }
-   }
-
-   public VirtualFileHandler getRoot() throws IOException
-   {
-      return entries.get("").handler;
-   }
-
-   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;
-   }
-
-   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 long getLastModified(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      checkIfModified();
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      if(ei == null)
-         return 0;
-
-      if(ei.entry == null) {
-         return zipSource.getLastModified();
-      }
-
-      return ei.entry.getTime();
-   }
-
-   public long getSize(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      checkIfModified();
-      String pathName = handler.getLocalPathName();
-      EntryInfo ei = entries.get(pathName);
-      if(ei == null)
-         return 0;
-
-      if(ei.entry == null)
-      {
-         if(pathName.length() == 0)
-            return zipSource.getSize();
-         else
-            return 0;
-      }
-
-      return ei.entry.getSize();
-   }
-
-   public boolean exists(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      checkIfModified();
-      String pathName = handler.getLocalPathName();
-      EntryInfo ei = entries.get(pathName);
-      if(ei == null)
-         return false;
-
-      if (ei.entry == null && pathName.length() == 0)
-         return zipSource.exists();
-
-      return true;
-   }
-
-   public boolean isLeaf(ZipEntryHandler handler)
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      checkIfModified();
-      EntryInfo ei = entries.get(handler.getLocalPathName());
-      if(ei == null || ei.entry == null)
-         return false;
-
-      return !ei.entry.isDirectory();
-   }
-
-   public InputStream openStream(ZipEntryHandler handler) throws IOException
-   {
-      if (handler == null)
-         throw new IllegalArgumentException("Null handler");
-
-      checkIfModified();
-
-      String localPathName = handler.getLocalPathName();
-      EntryInfo ei = entries.get(localPathName);
-
-      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)
-      {
-         if ("".equals(localPathName))  // root
-            return zipSource.getRootAsStream();
-         else                           // directory
-            return new ByteArrayInputStream(new byte[0]);
-      }
-      
-      return zipSource.openStream(ei.entry);
-   }
-
-   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);
-   }
-
-
-
-   protected void finalize()
-   {
-      try
-      {
-         super.finalize();
-         zipSource.close();
-      }
-      catch (Throwable ignored)
-      {
-         log.debug("IGNORING: Failed to close zip source: " + zipSource, ignored);
-      }
-   }
-
-
-   public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
-      if (parentEntry != null)
-      {
-         DelegatingHandler newOne;
-
-         if (replacement instanceof DelegatingHandler)
-         {
-            newOne = (DelegatingHandler) replacement;
-         }
-         else
-         {
-            DelegatingHandler delegator = new DelegatingHandler(this, parent, original.getName(), replacement);
-            newOne = delegator;
-         }
-
-         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
-   {
-      private AbstractVirtualFileHandler handler;
-      private ZipEntry entry;
-      private List<AbstractVirtualFileHandler> children;
-
-      EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
-      {
-         this.handler = handler;
-         this.entry = entry;
-      }
-
-      public synchronized List<VirtualFileHandler> getChildren()
-      {
-         if (children == null)
-            return Collections.emptyList();
-
-         return new LinkedList<VirtualFileHandler>(children);
-      }
-
-      public synchronized void replaceChild(AbstractVirtualFileHandler original, AbstractVirtualFileHandler replacement)
-      {
-         if (children != null)
-         {
-            int i = 0;
-            Iterator<AbstractVirtualFileHandler> it = children.iterator();
-            while(it.hasNext())
-            {
-               AbstractVirtualFileHandler child = it.next();
-               if (child.getName().equals(original.getName()))
-               {
-                  children.set(i, replacement);
-                  break;
-               }
-               i++;
-            }
-         }
-      }
-
-      public synchronized void clearChildren()
-      {
-         if (children != null)
-            children.clear();
-      }
-
-      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
-   //
-
-
-
-   /**
-    * Copy input stream to output stream and close them both
-    *
-    * @param is
-    * @param os
-    * @throws IOException
-    */
-   static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException
-   {
-      try
-      {
-         byte [] buff = new byte[65536];
-         int count = is.read(buff);
-         while(count != -1)
-         {
-            os.write(buff, 0, count);
-            count = is.read(buff);
-         }
-      }
-      finally
-      {
-         if(is != null)
-         {
-            try {
-               is.close();
-            }
-            catch(Exception ignored)
-            {
-            }
-         }
-         os.close();
-      }
-   }
-
-   /**
-    * Make sure url protocol is <em>vfszip</em>
-    *
-    * @param rootURL
-    * @return
-    * @throws MalformedURLException
-    */
-   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
-    * @return
-    */
-   public static String [] splitParentChild(String pathName)
-   {
-      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
-    * @return
-    */
-   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' sub-directory inside it for our purposes
-    *
-    * @return
-    */
-   private static String getTempDir()
-   {
-      File dir = new File(VFSUtils.getTempDirectory(), "vfs-nested.tmp");
-      return dir.toString();
-   }
-
-   /**
-    * Delete first-level files only, don't drill down
-    */
-   private static void deleteTmpDirContents()
-   {
-      try
-      {
-         File tmpDir = new File(getTempDir());
-         File [] files = tmpDir.listFiles();
-         for (File file: files)
-         {
-            if (!file.isDirectory() && !file.isHidden())
-               file.delete();
-         }
-      }
-      catch(Exception ignored)
-      {
-      }
-
-   }
-
-
-   private static class CheckForceCopy implements PrivilegedAction<Boolean>
-   {
-      public Boolean run()
-      {
-         String forceString = System.getProperty(VFSUtils.FORCE_COPY_KEY, "false");
-         return Boolean.valueOf(forceString);
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,977 @@
+/*
+* 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.File;
+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 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.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>ZipStremWrapper</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>.
+ *
+ * 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
+{
+   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 ConcurrentHashMap<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
+
+   /**
+    * 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 that couldn't fit 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);
+
+         String noReaper = getOptions().get(VFSUtils.NO_REAPER_QUERY);
+         zipSource = new ZipFileWrapper(VFSUtils.toURI(new URL(rootPath)), autoClean, Boolean.valueOf(noReaper));
+      }
+      else
+      {
+         zipSource = zipWrapper;
+      }
+      
+      setRootPeer(peer);
+
+      String name = getRootURI().toString();
+      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));
+
+      initEntries();
+      ZipEntryContextFactory.registerContext(this);
+   }
+
+   /**
+    * 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
+
+      HashMap<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);
+            }
+         }
+
+         TreeMap<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 = 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));
+                  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();
+      }
+   }
+
+   /**
+    * 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);
+
+      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);
+
+      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 "file:" + filePath;
+   }
+
+   /**
+    * If archive has been modified, clear <em>entries</em> and re-initialize
+    */
+   private synchronized void checkIfModified()
+   {
+      // TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
+      if (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);
+            }
+         }
+      }
+   }
+
+   public VirtualFileHandler getRoot() throws IOException
+   {
+      return entries.get("").handler;
+   }
+
+   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;
+   }
+
+   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 long getLastModified(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null)
+         return 0;
+
+      if(ei.entry == null) {
+         return zipSource.getLastModified();
+      }
+
+      return ei.entry.getTime();
+   }
+
+   public long getSize(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      checkIfModified();
+      String pathName = handler.getLocalPathName();
+      EntryInfo ei = entries.get(pathName);
+      if(ei == null)
+         return 0;
+
+      if(ei.entry == null)
+      {
+         if(pathName.length() == 0)
+            return zipSource.getSize();
+         else
+            return 0;
+      }
+
+      return ei.entry.getSize();
+   }
+
+   public boolean exists(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      checkIfModified();
+      String pathName = handler.getLocalPathName();
+      EntryInfo ei = entries.get(pathName);
+      if(ei == null)
+         return false;
+
+      if (ei.entry == null && pathName.length() == 0)
+         return zipSource.exists();
+
+      return true;
+   }
+
+   public boolean isLeaf(ZipEntryHandler handler)
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null || ei.entry == null)
+         return false;
+
+      return !ei.entry.isDirectory();
+   }
+
+   /**
+    * 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;
+   }
+
+   public InputStream openStream(ZipEntryHandler handler) throws IOException
+   {
+      if (handler == null)
+         throw new IllegalArgumentException("Null handler");
+
+      checkIfModified();
+
+      String localPathName = handler.getLocalPathName();
+      EntryInfo ei = entries.get(localPathName);
+
+      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)
+      {
+         if ("".equals(localPathName))  // root
+            return zipSource.getRootAsStream();
+         else                           // directory
+            return new ByteArrayInputStream(new byte[0]);
+      }
+      
+      return zipSource.openStream(ei.entry);
+   }
+
+   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);
+   }
+
+   protected void finalize()
+   {
+      try
+      {
+         super.finalize();
+         zipSource.close();
+      }
+      catch (Throwable ignored)
+      {
+         log.debug("IGNORING: Failed to close zip source: " + zipSource, ignored);
+      }
+   }
+
+   public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      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
+   {
+      private AbstractVirtualFileHandler handler;
+      private ZipEntry entry;
+      private List<AbstractVirtualFileHandler> children;
+
+      EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
+      {
+         this.handler = handler;
+         this.entry = entry;
+      }
+
+      public synchronized List<VirtualFileHandler> getChildren()
+      {
+         if (children == null)
+            return Collections.emptyList();
+
+         return new LinkedList<VirtualFileHandler>(children);
+      }
+
+      public synchronized void replaceChild(AbstractVirtualFileHandler original, AbstractVirtualFileHandler replacement)
+      {
+         if (children != null)
+         {
+            int i = 0;
+            Iterator<AbstractVirtualFileHandler> it = children.iterator();
+            while(it.hasNext())
+            {
+               AbstractVirtualFileHandler child = it.next();
+               if (child.getName().equals(original.getName()))
+               {
+                  children.set(i, replacement);
+                  break;
+               }
+               i++;
+            }
+         }
+      }
+
+      public synchronized void clearChildren()
+      {
+         if (children != null)
+            children.clear();
+      }
+
+      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
+   //
+
+   /**
+    * Copy input stream to output stream and close them both
+    *
+    * @param is input stream
+    * @param os output stream
+    * @throws IOException for any error
+    */
+   static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException
+   {
+      try
+      {
+         byte [] buff = new byte[65536];
+         int count = is.read(buff);
+         while(count != -1)
+         {
+            os.write(buff, 0, count);
+            count = is.read(buff);
+         }
+      }
+      finally
+      {
+         if(is != null)
+         {
+            try {
+               is.close();
+            }
+            catch(Exception ignored)
+            {
+            }
+         }
+         os.close();
+      }
+   }
+
+   /**
+    * 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.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' sub-directory inside it for our purposes
+    *
+    * @return temp dir
+    */
+   private static String getTempDir()
+   {
+      File dir = new File(VFSUtils.getTempDirectory(), "vfs-nested.tmp");
+      return dir.toString();
+   }
+
+   /**
+    * Delete first-level files only, don't drill down
+    */
+   private static void deleteTmpDirContents()
+   {
+      try
+      {
+         File tmpDir = new File(getTempDir());
+         File [] files = tmpDir.listFiles();
+         for (File file: files)
+         {
+            if (!file.isDirectory() && !file.isHidden())
+               file.delete();
+         }
+      }
+      catch(Exception ignored)
+      {
+      }
+   }
+
+   private static class CheckForceCopy implements PrivilegedAction<Boolean>
+   {
+      public Boolean run()
+      {
+         String forceString = System.getProperty(VFSUtils.FORCE_COPY_KEY, "false");
+         return Boolean.valueOf(forceString);
+      }
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,158 +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 org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-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.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * 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 final URL url;
-
-
-   /**
-    * 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
-    */
-   public ZipEntryHandler(ZipEntryContext context, AbstractVirtualFileHandler parent, String name, boolean isLeaf) throws IOException
-   {
-      super(context, parent, name);
-
-      url = context.getChildURL(parent, name);
-
-      String currentUrl = url.toString();
-      int pos = currentUrl.indexOf(":/");
-      StringBuilder vfsUrl = new StringBuilder();
-      vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
-      try
-      {
-         if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
-            vfsUrl.append("/");
-         setVfsUrl(new URL(vfsUrl.toString()));
-      }
-      catch(MalformedURLException ex)
-      {
-         throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
-      }
-
-      if(parent != null)
-      {
-         context.addChild(parent, this);
-      }
-   }
-
-   public URI toURI() throws URISyntaxException
-   {
-      return VFSUtils.toURI(url);
-   }
-
-   public long getLastModified() throws IOException
-   {
-      return getZipEntryContext().getLastModified(this);
-   }
-
-   public long getSize() throws IOException
-   {
-      return getZipEntryContext().getSize(this);
-   }
-
-   public boolean exists() throws IOException
-   {
-      return getZipEntryContext().exists(this);
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().isLeaf(this);
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      checkClosed();
-      return false;
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      checkClosed();
-      return getZipEntryContext().openStream(this);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      return getZipEntryContext().getChildren(this, ignoreErrors);
-
-   }
-
-   public VirtualFileHandler getChild(String path) throws IOException
-   {
-      return structuredFindChild(path);
-   }
-
-
-   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) getVFSContext());
-   }
-
-
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,154 @@
+/*
+* 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 final URL url;
+
+   /**
+    * 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);
+
+      url = context.getChildURL(parent, name);
+
+      String currentUrl = url.toString();
+      int pos = currentUrl.indexOf(":/");
+      StringBuilder vfsUrl = new StringBuilder();
+      vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
+      try
+      {
+         if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
+            vfsUrl.append("/");
+         setVfsUrl(new URL(vfsUrl.toString()));
+      }
+      catch(MalformedURLException ex)
+      {
+         throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
+      }
+
+      if(parent != null)
+      {
+         context.addChild(parent, this);
+      }
+   }
+
+   public URI toURI() throws URISyntaxException
+   {
+      return VFSUtils.toURI(url);
+   }
+
+   public long getLastModified() throws IOException
+   {
+      return getZipEntryContext().getLastModified(this);
+   }
+
+   public long getSize() throws IOException
+   {
+      return getZipEntryContext().getSize(this);
+   }
+
+   public boolean exists() throws IOException
+   {
+      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
+   {
+      return getZipEntryContext().getChildren(this, ignoreErrors);
+   }
+
+   public VirtualFileHandler getChild(String path) throws IOException
+   {
+      return structuredFindChild(path);
+   }
+
+   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) getVFSContext());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,204 +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 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;
-
-   /**
-    * 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);
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java (from rev 74087, projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/main/java/org/jboss/virtual/spi/VirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,220 @@
+/*
+ * 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;
+
+   /**
+    * 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;
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,289 +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.support;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.jboss.util.UnexpectedThrowable;
-import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * AbstractMockVirtualFileHandler.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public abstract class AbstractMockVirtualFileHandler extends AbstractVirtualFileHandler
-{
-   /** The serialVersionUID */
-   private static final long serialVersionUID = -7967261672121081602L;
-
-   /** The URI */
-   private URI uri;
-
-   /** The children */
-   private List<VirtualFileHandler> children = new CopyOnWriteArrayList<VirtualFileHandler>();
-
-   /** Last modified */
-   private long lastModified;
-   
-   /** Size */
-   private long size;
-   
-   /** Does the file exist */
-   private boolean exists = true;
-
-   /** Is a leaf */
-   private boolean leaf = true;
-   
-   /** Is a hidden */
-   private boolean hidden;
-   
-   /** The stream */
-   private byte[] stream;
-   
-   /** When to throw an IOException */
-   private String ioException = "";
-   
-   /**
-    * Create a root mock uri
-    * 
-    * @param context the vfs context
-    * @param parent the parent file
-    * @param name the name
-    * @return the uri
-    */
-   public static URI createMockURI(VFSContext context, VirtualFileHandler parent, String name)
-   {
-      try
-      {
-         String uri;
-         if (parent != null)
-            uri = parent.toURI().toString();
-         else
-            uri = context.getRootURI().toString();
-         if (name.length() != 0)
-            uri = uri + "/" + name;
-         return new URI(uri);
-      }
-      catch (URISyntaxException e)
-      {
-         throw new UnexpectedThrowable("Unexpected", e);
-      }
-   }
-
-   /**
-    * Create a new AbstractMockVirtualFileHandler.
-    * 
-    * @param context the context
-    * @param parent the parent
-    * @param name the name
-    */
-   protected AbstractMockVirtualFileHandler(MockVFSContext context, AbstractMockVirtualFileHandler parent, String name)
-   {
-      super(context, parent, name);
-      this.uri = createMockURI(context, parent, name);
-      if (parent != null)
-         parent.addChild(this);
-   }
-
-   /**
-    * Set the ioException.
-    * 
-    * @param ioException the ioException.
-    */
-   public void setIOException(String ioException)
-   {
-      this.ioException = ioException;
-   }
-
-   /**
-    * Check whether we should throw an IOException
-    * 
-    * @param when when to throw
-    * @throws IOException when requested
-    */
-   public void throwIOException(String when) throws IOException
-   {
-      if (ioException.equals(when))
-         throw new IOException("Throwing IOException from " + when);
-   }
-
-   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
-   {
-      checkClosed();
-      if (ignoreErrors == false)
-         throwIOException("getChildren");
-      return Collections.unmodifiableList(children);
-   }
-
-   public void addChild(VirtualFileHandler child)
-   {
-      checkClosed();
-      if (child == null)
-         throw new IllegalArgumentException("Null child");
-      if (children.contains(child) == false)
-         children.add(child);
-      leaf = false;
-   }
-
-   public long getLastModified() throws IOException
-   {
-      checkClosed();
-      throwIOException("getLastModified");
-      return lastModified;
-   }
-
-   /**
-    * Set the lastModified.
-    * 
-    * @param lastModified the lastModified.
-    */
-   public void setLastModified(long lastModified)
-   {
-      this.lastModified = lastModified;
-   }
-
-   public long getSize() throws IOException
-   {
-      checkClosed();
-      throwIOException("getSize");
-      return size;
-   }
-
-   /**
-    * Set the size.
-    * 
-    * @param size the size.
-    */
-   public void setSize(long size)
-   {
-      this.size = size;
-   }
-
-   public boolean exists()
-   {
-      return exists;
-   }
-
-   public void setExists(boolean exists)
-   {
-      this.exists = exists;
-   }
-
-   public boolean isLeaf() throws IOException
-   {
-      checkClosed();
-      throwIOException("isLeaf");
-      return leaf;
-   }
-
-   /**
-    * Set leaf.
-    * 
-    * @param leaf whether this is a leaf.
-    */
-   public void setLeaf(boolean leaf)
-   {
-      this.leaf = leaf;
-   }
-
-   public boolean isHidden() throws IOException
-   {
-      checkClosed();
-      throwIOException("isHidden");
-      return hidden;
-   }
-
-   /**
-    * Set the hidden.
-    * 
-    * @param hidden the hidden.
-    */
-   public void setHidden(boolean hidden)
-   {
-      this.hidden = hidden;
-   }
-
-   /**
-    * Set the stream.
-    * 
-    * @param stream the stream.
-    */
-   public void setStream(byte[] stream)
-   {
-      this.stream = stream;
-   }
-
-   public InputStream openStream() throws IOException
-   {
-      checkClosed();
-      throwIOException("openStream");
-      return new MockInputStream(stream);
-   }
-
-   public URI toURI()
-   {
-      return uri;
-   }
-
-
-   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
-   {
-      return toURL();
-   }
-
-   @Override
-   public URL toURL() throws MalformedURLException, URISyntaxException
-   {
-      return MockVFSContext.createMockURL(uri);
-   }
-
-   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
-   {
-      children.remove(original);
-      children.add(replacement);
-   }
-
-   @Override
-   public VirtualFileHandler getParent() throws IOException
-   {
-      throwIOException("getParent");
-      return super.getParent();
-   }
-
-   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
-   {
-      in.defaultReadObject();
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java (from rev 74087, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/support/AbstractMockVirtualFileHandler.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,302 @@
+/*
+* 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.support;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.jboss.util.UnexpectedThrowable;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * AbstractMockVirtualFileHandler.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractMockVirtualFileHandler extends AbstractVirtualFileHandler
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -7967261672121081602L;
+
+   /** The URI */
+   private URI uri;
+
+   /** The children */
+   private List<VirtualFileHandler> children = new CopyOnWriteArrayList<VirtualFileHandler>();
+
+   /** Last modified */
+   private long lastModified;
+   
+   /** Size */
+   private long size;
+   
+   /** Does the file exist */
+   private boolean exists = true;
+
+   /** Is a leaf */
+   private boolean leaf = true;
+   
+   /** Is a hidden */
+   private boolean hidden;
+
+   /** Is nested */
+   private boolean nested;
+
+   /** The stream */
+   private byte[] stream;
+   
+   /** When to throw an IOException */
+   private String ioException = "";
+   
+   /**
+    * Create a root mock uri
+    * 
+    * @param context the vfs context
+    * @param parent the parent file
+    * @param name the name
+    * @return the uri
+    */
+   public static URI createMockURI(VFSContext context, VirtualFileHandler parent, String name)
+   {
+      try
+      {
+         String uri;
+         if (parent != null)
+            uri = parent.toURI().toString();
+         else
+            uri = context.getRootURI().toString();
+         if (name.length() != 0)
+            uri = uri + "/" + name;
+         return new URI(uri);
+      }
+      catch (URISyntaxException e)
+      {
+         throw new UnexpectedThrowable("Unexpected", e);
+      }
+   }
+
+   /**
+    * Create a new AbstractMockVirtualFileHandler.
+    * 
+    * @param context the context
+    * @param parent the parent
+    * @param name the name
+    */
+   protected AbstractMockVirtualFileHandler(MockVFSContext context, AbstractMockVirtualFileHandler parent, String name)
+   {
+      super(context, parent, name);
+      this.uri = createMockURI(context, parent, name);
+      if (parent != null)
+         parent.addChild(this);
+   }
+
+   /**
+    * Set the ioException.
+    * 
+    * @param ioException the ioException.
+    */
+   public void setIOException(String ioException)
+   {
+      this.ioException = ioException;
+   }
+
+   /**
+    * Check whether we should throw an IOException
+    * 
+    * @param when when to throw
+    * @throws IOException when requested
+    */
+   public void throwIOException(String when) throws IOException
+   {
+      if (ioException.equals(when))
+         throw new IOException("Throwing IOException from " + when);
+   }
+
+   public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+   {
+      checkClosed();
+      if (ignoreErrors == false)
+         throwIOException("getChildren");
+      return Collections.unmodifiableList(children);
+   }
+
+   public void addChild(VirtualFileHandler child)
+   {
+      checkClosed();
+      if (child == null)
+         throw new IllegalArgumentException("Null child");
+      if (children.contains(child) == false)
+         children.add(child);
+      leaf = false;
+   }
+
+   public long getLastModified() throws IOException
+   {
+      checkClosed();
+      throwIOException("getLastModified");
+      return lastModified;
+   }
+
+   /**
+    * Set the lastModified.
+    * 
+    * @param lastModified the lastModified.
+    */
+   public void setLastModified(long lastModified)
+   {
+      this.lastModified = lastModified;
+   }
+
+   public long getSize() throws IOException
+   {
+      checkClosed();
+      throwIOException("getSize");
+      return size;
+   }
+
+   /**
+    * Set the size.
+    * 
+    * @param size the size.
+    */
+   public void setSize(long size)
+   {
+      this.size = size;
+   }
+
+   public boolean exists()
+   {
+      return exists;
+   }
+
+   public void setExists(boolean exists)
+   {
+      this.exists = exists;
+   }
+
+   public boolean isLeaf() throws IOException
+   {
+      checkClosed();
+      throwIOException("isLeaf");
+      return leaf;
+   }
+
+   /**
+    * Set leaf.
+    * 
+    * @param leaf whether this is a leaf.
+    */
+   public void setLeaf(boolean leaf)
+   {
+      this.leaf = leaf;
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      checkClosed();
+      throwIOException("isHidden");
+      return hidden;
+   }
+
+   /**
+    * Set the hidden.
+    * 
+    * @param hidden the hidden.
+    */
+   public void setHidden(boolean hidden)
+   {
+      this.hidden = hidden;
+   }
+
+   public boolean isNested() throws IOException
+   {
+      return nested;
+   }
+
+   public void setNested(boolean nested)
+   {
+      this.nested = nested;
+   }
+
+   /**
+    * Set the stream.
+    * 
+    * @param stream the stream.
+    */
+   public void setStream(byte[] stream)
+   {
+      this.stream = stream;
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      checkClosed();
+      throwIOException("openStream");
+      return new MockInputStream(stream);
+   }
+
+   public URI toURI()
+   {
+      return uri;
+   }
+
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      return toURL();
+   }
+
+   @Override
+   public URL toURL() throws MalformedURLException, URISyntaxException
+   {
+      return MockVFSContext.createMockURL(uri);
+   }
+
+   protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+   {
+      children.remove(original);
+      children.add(replacement);
+   }
+
+   @Override
+   public VirtualFileHandler getParent() throws IOException
+   {
+      throwIOException("getParent");
+      return super.getParent();
+   }
+
+   private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+   {
+      in.defaultReadObject();
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,601 +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.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import org.jboss.virtual.VirtualFile;
-import org.jboss.virtual.spi.VFSContext;
-import org.jboss.virtual.spi.VirtualFileHandler;
-
-/**
- * AbstractVirtualFileHandlerTest.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public abstract class AbstractVirtualFileHandlerTest extends AbstractVFSTest
-{
-   public AbstractVirtualFileHandlerTest(String name)
-   {
-      super(name);
-   }
-   
-   protected abstract VFSContext getVFSContext(String name) throws Exception;
-
-   protected String getRootName(String name) throws Exception
-   {
-      return name;
-   }
-   
-   protected abstract long getRealLastModified(String name, String path) throws Exception;
-   
-   protected abstract long getRealSize(String name, String path) throws Exception;
-   
-   public void testRootName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      String rootName = getRootName("complex");
-      assertEquals(rootName, root.getName());
-   }
-
-   public void testChildName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      assertEquals("child", child.getName());
-   }
-
-   public void testSubFolderName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder");
-      assertEquals("subfolder", child.getName());
-   }
-
-   public void testSubChildName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
-      assertTrue(child.getName().endsWith("subchild"));
-   }
-   
-   public void testRootPathName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      assertEquals("", root.getPathName());
-   }
-
-   public void testChildPathName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      assertEquals("child", child.getPathName());
-   }
-
-   public void testSubFolderPathName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder");
-      assertEquals("subfolder", child.getPathName());
-   }
-
-   public void testSubChildPathName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
-      assertEquals("subfolder/subchild", child.getPathName());
-   }
-
-   /**
-    * Test that finding a child and listing its parent result in consistent
-    * child handlers.
-    * 
-    * @throws Exception
-    */
-   public void testSubSubChildPathName() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder/subsubfolder/subsubchild");
-      assertEquals("subfolder/subsubfolder/subsubchild", child.getPathName());
-      VirtualFileHandler parent = context.getChild(root, "subfolder/subsubfolder");
-      List<VirtualFileHandler> children = parent.getChildren(false);
-      // Filter out an .svn stuff since this is run from the source tree
-      Iterator<VirtualFileHandler> iter = children.iterator();
-      while( iter.hasNext() )
-      {
-         child = iter.next();
-         if( child.getName().endsWith(".svn") )
-          iter.remove();
-      }
-      assertEquals("subfolder/subsubfolder has one child", 1, children.size());
-      child = children.get(0);
-      assertEquals("subfolder/subsubfolder/subsubchild", child.getPathName());
-   }
-
-   /* TODO URI testing
-   public void testToURI() throws Exception
-   {
-   }
-   */
-
-   /* TODO URL testing
-   public void testToURL() throws Exception
-   {
-   }
-   */
-   
-   public void testRootLastModified() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      long realLastModified = getRealLastModified("simple", null);
-      // strip any milliseconds
-      realLastModified = realLastModified / 1000 * 1000;
-      long fileLastModified = root.getLastModified();
-      fileLastModified = fileLastModified / 1000 * 1000;
-      assertEquals(realLastModified, fileLastModified);
-   }
-   
-   public void testChildLastModified() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      long realLastModified = getRealLastModified("simple", "child");
-      assertEquals(realLastModified, child.getLastModified());
-   }
-
-   public void testGetLastModifiedClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getLastModified();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-   
-   public void testRootSize() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      long realSize = getRealSize("simple", null);
-      assertEquals(realSize, root.getSize());
-   }
-   
-   public void testChildSize() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      long realSize = getRealSize("simple", "child");
-      assertEquals(realSize, child.getSize());
-   }
-
-   public void testGetSizeClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getSize();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-   
-   public void testRootIsLeaf() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      assertFalse(root.isLeaf());
-   }
-
-   public void testChildIsLeaf() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      assertTrue(child.isLeaf());
-   }
-
-   public void testSubFolderIsLeaf() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder");
-      assertFalse(child.isLeaf());
-   }
-
-   public void testSubChildIsLeaf() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
-      assertTrue(child.isLeaf());
-   }
-
-   public void testIsLeafClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.isLeaf();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   // TODO how to test a real hidden file across platforms?
-   public void testRootIsHidden() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      assertFalse(root.isHidden());
-   }
-   
-   // TODO how to test a real hidden file across platforms?
-   public void testChildIsHidden() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      assertFalse(child.isHidden());
-   }
-
-   public void testIsHiddenClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.isHidden();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   public void testOpenStream() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      InputStream stream = child.openStream();
-      try
-      {
-         byte[] contents = new byte[10];
-         int read = stream.read(contents);
-         int total = 0;
-         while (read != -1)
-         {
-            total += read;
-            read = stream.read(contents, total, 10-total);
-         }
-         assertEquals(5, total);
-         assertTrue(Arrays.equals("empty\0\0\0\0\0".getBytes(), contents));
-      }
-      finally
-      {
-         stream.close();
-      }
-   }
-
-   public void testOpenStreamClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.openStream();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   public void testRootParent() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      assertNull(root.getParent());
-   }
-   
-   public void testChildParent() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      assertEquals(root, child.getParent());
-   }
-
-   public void testgetParentClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getParent();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   public void testGetChildren() throws Exception
-   {
-      VFSContext context = getVFSContext("children");
-      VirtualFileHandler root = context.getRoot();
-      List<VirtualFileHandler> children = root.getChildren(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 testGetChildrenClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getChildren(false);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   public void testFindChildRoot() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = root.getChild("");
-      assertEquals(root, found);
-   }
-
-   public void testFindChild() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = root.getChild("child");
-      assertEquals("child", found.getPathName());
-   }
-
-   public void testFindChildSubFolder() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = root.getChild("subfolder");
-      assertEquals("subfolder", found.getPathName());
-   }
-
-   public void testFindChildSubChild() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler found = root.getChild("subfolder/subchild");
-      assertEquals("subfolder/subchild", found.getPathName());
-   }
-
-   public void testFindChildDoesNotExist() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      try
-      {
-         VirtualFileHandler child = root.getChild("doesnotexist");
-         assertNull(child);
-      }
-      catch (Throwable t)
-      {
-         checkThrowableTemp(IOException.class, t);
-      }
-   }
-
-   public void testFindChildNullPath() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      try
-      {
-         root.getChild(null);
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalArgumentException.class, t);
-      }
-   }
-
-   public void testFindChildClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getChild("");
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   public void testGetVFSContext() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler handler = context.getRoot();
-      assertEquals(context, handler.getVFSContext());
-   }
-
-   public void testGetVFSContextClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getVFSContext();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-  
-   public void testRootGetVirtualFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      checkVirtualFile(root);
-   }
-
-   public void testChildGetVirtualFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      checkVirtualFile(child);
-   }
-
-   public void testSubFolderGetVirtualFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder");
-      checkVirtualFile(child);
-   }
-
-   public void testSubChildGetVirtualFile() throws Exception
-   {
-      VFSContext context = getVFSContext("complex");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
-      checkVirtualFile(child);
-   }
-
-   public void testGetVirtualFileClosed() throws Exception
-   {
-      VFSContext context = getVFSContext("simple");
-      VirtualFileHandler root = context.getRoot();
-      VirtualFileHandler child = context.getChild(root, "child");
-      child.close();
-      try
-      {
-         child.getVirtualFile();
-         fail("Should not be here!");
-      }
-      catch (Throwable t)
-      {
-         checkThrowable(IllegalStateException.class, t);
-      }
-   }
-
-   protected void checkVirtualFile(VirtualFileHandler handler) throws Exception
-   {
-      VirtualFile file = handler.getVirtualFile();
-      
-      assertEquals(handler.getVFSContext().getVFS(), file.getVFS());
-      assertEquals(handler.getName(), file.getName());
-      assertEquals(handler.getPathName(), file.getPathName());
-      assertEquals(handler.isHidden(), file.isHidden());
-      assertEquals(handler.isLeaf(), file.isLeaf());
-      assertEquals(handler.getLastModified(), file.getLastModified());
-      assertEquals(handler.getSize(), file.getSize());
-
-      // can't do this anymore as VirtualFile.toURL() returns a vfs based url
-      //assertEquals(handler.toURI(), file.toURI());
-      //assertEquals(handler.toURL(), file.toURL());
-      
-      VirtualFileHandler parent = handler.getParent();
-      if (parent == null)
-         assertNull(file.getParent());
-      else
-         assertEquals(parent.getVirtualFile(), file.getParent());
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java (from rev 74087, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/AbstractVirtualFileHandlerTest.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,618 @@
+/*
+* 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.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * AbstractVirtualFileHandlerTest.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractVirtualFileHandlerTest extends AbstractVFSTest
+{
+   public AbstractVirtualFileHandlerTest(String name)
+   {
+      super(name);
+   }
+   
+   protected abstract VFSContext getVFSContext(String name) throws Exception;
+
+   protected String getRootName(String name) throws Exception
+   {
+      return name;
+   }
+   
+   protected abstract long getRealLastModified(String name, String path) throws Exception;
+   
+   protected abstract long getRealSize(String name, String path) throws Exception;
+   
+   public void testRootName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      String rootName = getRootName("complex");
+      assertEquals(rootName, root.getName());
+   }
+
+   public void testChildName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      assertEquals("child", child.getName());
+   }
+
+   public void testSubFolderName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder");
+      assertEquals("subfolder", child.getName());
+   }
+
+   public void testSubChildName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
+      assertTrue(child.getName().endsWith("subchild"));
+   }
+   
+   public void testRootPathName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      assertEquals("", root.getPathName());
+   }
+
+   public void testChildPathName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      assertEquals("child", child.getPathName());
+   }
+
+   public void testSubFolderPathName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder");
+      assertEquals("subfolder", child.getPathName());
+   }
+
+   public void testSubChildPathName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
+      assertEquals("subfolder/subchild", child.getPathName());
+   }
+
+   /**
+    * Test that finding a child and listing its parent result in consistent
+    * child handlers.
+    * 
+    * @throws Exception
+    */
+   public void testSubSubChildPathName() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder/subsubfolder/subsubchild");
+      assertEquals("subfolder/subsubfolder/subsubchild", child.getPathName());
+      VirtualFileHandler parent = context.getChild(root, "subfolder/subsubfolder");
+      List<VirtualFileHandler> children = parent.getChildren(false);
+      // Filter out an .svn stuff since this is run from the source tree
+      Iterator<VirtualFileHandler> iter = children.iterator();
+      while( iter.hasNext() )
+      {
+         child = iter.next();
+         if( child.getName().endsWith(".svn") )
+          iter.remove();
+      }
+      assertEquals("subfolder/subsubfolder has one child", 1, children.size());
+      child = children.get(0);
+      assertEquals("subfolder/subsubfolder/subsubchild", child.getPathName());
+   }
+
+   /* TODO URI testing
+   public void testToURI() throws Exception
+   {
+   }
+   */
+
+   /* TODO URL testing
+   public void testToURL() throws Exception
+   {
+   }
+   */
+   
+   public void testRootLastModified() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      long realLastModified = getRealLastModified("simple", null);
+      // strip any milliseconds
+      realLastModified = realLastModified / 1000 * 1000;
+      long fileLastModified = root.getLastModified();
+      fileLastModified = fileLastModified / 1000 * 1000;
+      assertEquals(realLastModified, fileLastModified);
+   }
+   
+   public void testChildLastModified() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      long realLastModified = getRealLastModified("simple", "child");
+      assertEquals(realLastModified, child.getLastModified());
+   }
+
+   public void testGetLastModifiedClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getLastModified();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+   
+   public void testRootSize() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      long realSize = getRealSize("simple", null);
+      assertEquals(realSize, root.getSize());
+   }
+   
+   public void testChildSize() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      long realSize = getRealSize("simple", "child");
+      assertEquals(realSize, child.getSize());
+   }
+
+   public void testGetSizeClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getSize();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+   
+   public void testRootIsLeaf() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      assertFalse(root.isLeaf());
+   }
+
+   public void testChildIsLeaf() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      assertTrue(child.isLeaf());
+   }
+
+   public void testSubFolderIsLeaf() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder");
+      assertFalse(child.isLeaf());
+   }
+
+   public void testSubChildIsLeaf() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
+      assertTrue(child.isLeaf());
+   }
+
+   public void testIsLeafClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.isLeaf();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   // TODO how to test a real hidden file across platforms?
+   public void testRootIsHidden() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      assertFalse(root.isHidden());
+   }
+   
+   // TODO how to test a real hidden file across platforms?
+   public void testChildIsHidden() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      assertFalse(child.isHidden());
+   }
+
+   public void testIsHiddenClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.isHidden();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testOpenStream() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      InputStream stream = child.openStream();
+      try
+      {
+         byte[] contents = new byte[10];
+         int read = stream.read(contents);
+         int total = 0;
+         while (read != -1)
+         {
+            total += read;
+            read = stream.read(contents, total, 10-total);
+         }
+         assertEquals(5, total);
+         assertTrue(Arrays.equals("empty\0\0\0\0\0".getBytes(), contents));
+      }
+      finally
+      {
+         stream.close();
+      }
+   }
+
+   public void testOpenStreamClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.openStream();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testRootParent() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      assertNull(root.getParent());
+   }
+   
+   public void testChildParent() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      assertEquals(root, child.getParent());
+   }
+
+   public void testgetParentClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getParent();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testGetChildren() throws Exception
+   {
+      VFSContext context = getVFSContext("children");
+      VirtualFileHandler root = context.getRoot();
+      List<VirtualFileHandler> children = root.getChildren(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 testGetChildrenClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getChildren(false);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testFindChildRoot() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = root.getChild("");
+      assertEquals(root, found);
+   }
+
+   public void testFindChild() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = root.getChild("child");
+      assertEquals("child", found.getPathName());
+   }
+
+   public void testFindChildSubFolder() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = root.getChild("subfolder");
+      assertEquals("subfolder", found.getPathName());
+   }
+
+   public void testFindChildSubChild() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler found = root.getChild("subfolder/subchild");
+      assertEquals("subfolder/subchild", found.getPathName());
+   }
+
+   public void testFindChildDoesNotExist() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      try
+      {
+         VirtualFileHandler child = root.getChild("doesnotexist");
+         assertNull(child);
+      }
+      catch (Throwable t)
+      {
+         checkThrowableTemp(IOException.class, t);
+      }
+   }
+
+   public void testFindChildNullPath() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      try
+      {
+         root.getChild(null);
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalArgumentException.class, t);
+      }
+   }
+
+   public void testFindChildClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getChild("");
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testGetVFSContext() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler handler = context.getRoot();
+      assertEquals(context, handler.getVFSContext());
+   }
+
+   public void testGetVFSContextClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getVFSContext();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+  
+   public void testRootGetVirtualFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      checkVirtualFile(root);
+   }
+
+   public void testChildGetVirtualFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      checkVirtualFile(child);
+   }
+
+   public void testSubFolderGetVirtualFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder");
+      checkVirtualFile(child);
+   }
+
+   public void testSubChildGetVirtualFile() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "subfolder/subchild");
+      checkVirtualFile(child);
+   }
+
+   public void testGetVirtualFileClosed() throws Exception
+   {
+      VFSContext context = getVFSContext("simple");
+      VirtualFileHandler root = context.getRoot();
+      VirtualFileHandler child = context.getChild(root, "child");
+      child.close();
+      try
+      {
+         child.getVirtualFile();
+         fail("Should not be here!");
+      }
+      catch (Throwable t)
+      {
+         checkThrowable(IllegalStateException.class, t);
+      }
+   }
+
+   public void testIsNested() throws Exception
+   {
+      VFSContext context = getVFSContext("complex");
+      VirtualFileHandler root = context.getRoot();
+      assertFalse(root.isNested());
+      VirtualFileHandler subfolder = context.getChild(root, "subfolder");
+      assertIsNested(subfolder);
+      VirtualFileHandler subchild = subfolder.getChild("subchild");
+      assertIsNested(subchild);
+      VirtualFileHandler subsubfolder = subfolder.getChild("subsubfolder");
+      assertIsNested(subsubfolder);
+      VirtualFileHandler subsubchild = subsubfolder.getChild("subsubchild");
+      assertIsNested(subsubchild);
+   }
+
+   protected abstract void assertIsNested(VirtualFileHandler handler) throws Exception;
+
+   protected void checkVirtualFile(VirtualFileHandler handler) throws Exception
+   {
+      VirtualFile file = handler.getVirtualFile();
+      
+      assertEquals(handler.getVFSContext().getVFS(), file.getVFS());
+      assertEquals(handler.getName(), file.getName());
+      assertEquals(handler.getPathName(), file.getPathName());
+      assertEquals(handler.isHidden(), file.isHidden());
+      assertEquals(handler.isLeaf(), file.isLeaf());
+      assertEquals(handler.getLastModified(), file.getLastModified());
+      assertEquals(handler.getSize(), file.getSize());
+
+      // can't do this anymore as VirtualFile.toURL() returns a vfs based url
+      //assertEquals(handler.toURI(), file.toURI());
+      //assertEquals(handler.toURL(), file.toURL());
+      
+      VirtualFileHandler parent = handler.getParent();
+      if (parent == null)
+         assertNull(file.getParent());
+      else
+         assertEquals(parent.getVirtualFile(), file.getParent());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,81 +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.File;
-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;
-
-/**
- * FileVirtualFileHandlerUnitTestCase.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class FileVirtualFileHandlerUnitTestCase extends AbstractVirtualFileHandlerTest
-{
-   public FileVirtualFileHandlerUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(FileVirtualFileHandlerUnitTestCase.class);
-   }
-
-   protected URL getRootResource(String name) throws Exception
-   {
-      return getResource("/vfs/context/file/" + name + "/");
-   }
-   
-   protected File getRealFile(String name, String path) throws Exception
-   {
-      URL url = getRootResource(name);
-      if (path != null)
-         url = new URL(url, path);
-      return new File(url.getPath());
-   }
-   
-   protected VFSContext getVFSContext(String name) throws Exception
-   {
-      URL url = getRootResource(name);
-      return new FileSystemContext(url);
-   }
-
-   protected long getRealLastModified(String name, String path) throws Exception
-   {
-      File file = getRealFile(name, path);
-      return file.lastModified();
-   }
-
-   protected long getRealSize(String name, String path) throws Exception
-   {
-      File file = getRealFile(name, path);
-      return file.length();
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java (from rev 74087, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/FileVirtualFileHandlerUnitTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,88 @@
+/*
+* 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.File;
+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;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+/**
+ * FileVirtualFileHandlerUnitTestCase.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class FileVirtualFileHandlerUnitTestCase extends AbstractVirtualFileHandlerTest
+{
+   public FileVirtualFileHandlerUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(FileVirtualFileHandlerUnitTestCase.class);
+   }
+
+   protected URL getRootResource(String name) throws Exception
+   {
+      return getResource("/vfs/context/file/" + name + "/");
+   }
+   
+   protected File getRealFile(String name, String path) throws Exception
+   {
+      URL url = getRootResource(name);
+      if (path != null)
+         url = new URL(url, path);
+      return new File(url.getPath());
+   }
+   
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getRootResource(name);
+      return new FileSystemContext(url);
+   }
+
+   protected long getRealLastModified(String name, String path) throws Exception
+   {
+      File file = getRealFile(name, path);
+      return file.lastModified();
+   }
+
+   protected long getRealSize(String name, String path) throws Exception
+   {
+      File file = getRealFile(name, path);
+      return file.length();
+   }
+
+   protected void assertIsNested(VirtualFileHandler handler) throws Exception
+   {
+      assertNotNull(handler);
+      assertFalse(handler.isNested());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,116 +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.File;
-import java.net.JarURLConnection;
-import java.net.URL;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-import junit.framework.Test;
-import junit.framework.TestSuite;
-import org.jboss.virtual.plugins.context.jar.JarContext;
-import org.jboss.virtual.plugins.context.jar.JarUtils;
-import org.jboss.virtual.spi.VFSContext;
-
-/**
- * JARVirtualFileHandlerUnitTestCase.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision: 1.1 $
- */
-public class JARVirtualFileHandlerUnitTestCase extends AbstractVirtualFileHandlerTest
-{
-   public JARVirtualFileHandlerUnitTestCase(String name)
-   {
-      super(name);
-   }
-
-   public static Test suite()
-   {
-      return new TestSuite(JARVirtualFileHandlerUnitTestCase.class);
-   }
-   
-   protected URL getRootResource(String name) throws Exception
-   {
-      if (name.endsWith(".jar"))
-         return getResource("/vfs/context/jar/" + name);
-      else
-         return getResource("/vfs/context/jar/" + name + ".jar");
-   }
-   
-   protected File getRealJarFile(String name) throws Exception
-   {
-      URL url = getRootResource(name);
-      return new File(url.getPath());
-   }
-   
-   protected JarEntry getRealJarEntry(String name, String path) throws Exception
-   {
-      URL url = getRootResource(name);
-      url = JarUtils.createJarURL(url);
-      JarURLConnection c = (JarURLConnection) url.openConnection();
-      JarFile jarFile = c.getJarFile();
-      return jarFile.getJarEntry(path);
-   }
-   
-   protected VFSContext getVFSContext(String name) throws Exception
-   {
-      URL url = getRootResource(name);
-      url = JarUtils.createJarURL(url);
-      return new JarContext(url);
-   }
-
-   protected String getRootName(String name) throws Exception
-   {
-      return name + ".jar";
-   }
-
-   protected long getRealLastModified(String name, String path) throws Exception
-   {
-      if (path != null)
-      {
-         JarEntry entry = getRealJarEntry(name, path);
-         return entry.getTime();
-      }
-      else
-      {
-         File file = getRealJarFile(name);
-         return file.lastModified();
-      }
-   }
-
-   protected long getRealSize(String name, String path) throws Exception
-   {
-      if (path != null)
-      {
-         JarEntry entry = getRealJarEntry(name, path);
-         return entry.getSize();
-      }
-      else
-      {
-         File file = getRealJarFile(name);
-         return file.length();
-      }
-   }
-}

Copied: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java (from rev 74087, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/JARVirtualFileHandlerUnitTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,123 @@
+/*
+* 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.File;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+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;
+
+/**
+ * JARVirtualFileHandlerUnitTestCase.
+ * 
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class JARVirtualFileHandlerUnitTestCase extends AbstractVirtualFileHandlerTest
+{
+   public JARVirtualFileHandlerUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(JARVirtualFileHandlerUnitTestCase.class);
+   }
+   
+   protected URL getRootResource(String name) throws Exception
+   {
+      if (name.endsWith(".jar"))
+         return getResource("/vfs/context/jar/" + name);
+      else
+         return getResource("/vfs/context/jar/" + name + ".jar");
+   }
+   
+   protected File getRealJarFile(String name) throws Exception
+   {
+      URL url = getRootResource(name);
+      return new File(url.getPath());
+   }
+   
+   protected JarEntry getRealJarEntry(String name, String path) throws Exception
+   {
+      URL url = getRootResource(name);
+      url = JarUtils.createJarURL(url);
+      JarURLConnection c = (JarURLConnection) url.openConnection();
+      JarFile jarFile = c.getJarFile();
+      return jarFile.getJarEntry(path);
+   }
+   
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getRootResource(name);
+      url = JarUtils.createJarURL(url);
+      return new JarContext(url);
+   }
+
+   protected String getRootName(String name) throws Exception
+   {
+      return name + ".jar";
+   }
+
+   protected long getRealLastModified(String name, String path) throws Exception
+   {
+      if (path != null)
+      {
+         JarEntry entry = getRealJarEntry(name, path);
+         return entry.getTime();
+      }
+      else
+      {
+         File file = getRealJarFile(name);
+         return file.lastModified();
+      }
+   }
+
+   protected long getRealSize(String name, String path) throws Exception
+   {
+      if (path != null)
+      {
+         JarEntry entry = getRealJarEntry(name, path);
+         return entry.getSize();
+      }
+      else
+      {
+         File file = getRealJarFile(name);
+         return file.length();
+      }
+   }
+
+   protected void assertIsNested(VirtualFileHandler handler) throws Exception
+   {
+      assertNotNull(handler);
+      assertTrue(handler.toString(), handler.isNested());
+   }
+}

Deleted: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java	2008-06-04 05:57:34 UTC (rev 74078)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -1,182 +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.io.InputStream;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-
-import junit.framework.Test;
-import org.jboss.virtual.VFS;
-import org.jboss.virtual.VFSUtils;
-import org.jboss.virtual.VirtualFile;
-
-/**
- * Unpack tests.
- *
- * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
- */
-public class UnpackTestCase extends AbstractVFSTest
-{
-   public UnpackTestCase(String s)
-   {
-      super(s);
-   }
-
-   public static Test suite()
-   {
-      return suite(UnpackTestCase.class);
-   }
-
-   protected void assertNoReplacement(VFS vfs, String name) throws Throwable
-   {
-      VirtualFile original = vfs.findChild(name);
-      VirtualFile replacement = VFSUtils.unpack(original);
-      assertSame(original, replacement);
-   }
-
-   public void testNoReplacement() throws Throwable
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-
-      assertNoReplacement(vfs, "unpacked-outer.jar");
-      assertNoReplacement(vfs, "jar1-filesonly.mf");
-      assertNoReplacement(vfs, "unpacked-with-metadata.jar/META-INF");
-   }
-
-   public void testUnpackOuter() throws Throwable
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile original;
-      VirtualFile replacement;
-
-      original = vfs.findChild("outer.jar");
-      replacement = VFSUtils.unpack(original);
-      assertEquals(original.getParent(), replacement.getParent());
-
-      VirtualFile child = replacement.findChild("jar1.jar");
-      assertNotNull(child);
-      assertNotNull(child.findChild("META-INF/MANIFEST.MF"));
-      assertNotNull(replacement.findChild("jar2.jar"));
-   }
-
-   public void testUnpackTopLevel() throws Throwable
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile original;
-      VirtualFile replacement;
-
-      original = vfs.findChild("level1.zip");
-      replacement = VFSUtils.unpack(original);
-      assertReplacement(original, replacement);
-      VirtualFile parent = original.getParent();
-      VirtualFile child = parent.findChild("level1.zip");
-      assertEquals(replacement, child);
-
-      VirtualFile textOne = replacement.findChild("test1.txt");
-      testText(textOne);
-      VirtualFile two = replacement.findChild("level2.zip");
-      VirtualFile textTwo = two.findChild("test2.txt");
-      testText(textTwo);
-      VirtualFile three = two.findChild("level3.zip");
-      VirtualFile textThree = three.findChild("test3.txt");
-      testText(textThree);
-   }
-
-   public void testUnpack2ndLevel() throws Throwable
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile original;
-      VirtualFile replacement;
-
-      original = vfs.findChild("level1.zip/level2.zip");
-      replacement = VFSUtils.unpack(original);
-      assertReplacement(original, replacement);
-      VirtualFile parent = original.getParent();
-      VirtualFile child = parent.findChild("level2.zip");
-      //assertEquals(replacement, child);
-      assertEquals(replacement.toURI(), child.toURI());
-
-      VirtualFile textTwo = replacement.findChild("test2.txt");
-      testText(textTwo);
-      VirtualFile three = replacement.findChild("level3.zip");
-      VirtualFile textThree = three.findChild("test3.txt");
-      testText(textThree);
-   }
-
-   public void testUnpackDeepLevel() throws Throwable
-   {
-      URL rootURL = getResource("/vfs/test");
-      VFS vfs = VFS.getVFS(rootURL);
-      VirtualFile original;
-      VirtualFile replacement;
-
-      original = vfs.findChild("level1.zip/level2.zip/level3.zip");
-      replacement = VFSUtils.unpack(original);
-      assertReplacement(original, replacement);
-      VirtualFile parent = original.getParent();
-      VirtualFile child = parent.findChild("level3.zip");
-      //assertEquals(replacement, child);
-      assertEquals(replacement.toURI(), child.toURI());
-
-      VirtualFile textThree = replacement.findChild("test3.txt");
-      testText(textThree);
-   }
-
-   protected void assertReplacement(VirtualFile original, VirtualFile replacement) throws Exception
-   {
-      assertEquals(original.getName(), replacement.getName());
-      // when mounting via DelegatingHandler, getPathName changes because VFSContext changes
-      //assertEquals(original.getPathName(), replacement.getPathName());
-      
-      // it's a directory
-      assertEquals(0, replacement.getSize());
-      assertEquals(original.exists(), replacement.exists());
-      assertEquals(original.isLeaf(), replacement.isLeaf());
-      assertEquals(original.isHidden(), replacement.isHidden());
-      assertEquals(original.getParent(), replacement.getParent());
-   }
-
-   protected void testText(VirtualFile file) throws Exception
-   {
-      InputStream in = file.openStream();
-      try
-      {
-         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
-         String line;
-         while ((line = reader.readLine()) != null)
-         {
-            assertEquals("Some test.", line);
-         }
-      }
-      finally
-      {
-         in.close();
-      }
-   }
-}
\ No newline at end of file

Copied: projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java (from rev 74087, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java)
===================================================================
--- projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java	                        (rev 0)
+++ projects/vfs/tags/2.0.0.Beta13/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java	2008-06-04 12:18:45 UTC (rev 74090)
@@ -0,0 +1,181 @@
+/*
+* 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.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+
+/**
+ * Unpack tests.
+ *
+ * @author <a href="mailto:ales.justin at jboss.com">Ales Justin</a>
+ */
+public class UnpackTestCase extends AbstractVFSTest
+{
+   public UnpackTestCase(String s)
+   {
+      super(s);
+   }
+
+   public static Test suite()
+   {
+      return suite(UnpackTestCase.class);
+   }
+
+   protected void assertNoReplacement(VFS vfs, String name) throws Throwable
+   {
+      VirtualFile original = vfs.findChild(name);
+      VirtualFile replacement = VFSUtils.unpack(original);
+      assertSame(original, replacement);
+   }
+
+   public void testNoReplacement() throws Throwable
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      assertNoReplacement(vfs, "unpacked-outer.jar");
+      assertNoReplacement(vfs, "jar1-filesonly.mf");
+      assertNoReplacement(vfs, "unpacked-with-metadata.jar/META-INF");
+   }
+
+   public void testUnpackOuter() throws Throwable
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile original;
+      VirtualFile replacement;
+
+      original = vfs.findChild("outer.jar");
+      replacement = VFSUtils.unpack(original);
+      assertEquals(original.getParent(), replacement.getParent());
+
+      VirtualFile child = replacement.findChild("jar1.jar");
+      assertNotNull(child);
+      assertNotNull(child.findChild("META-INF/MANIFEST.MF"));
+      assertNotNull(replacement.findChild("jar2.jar"));
+   }
+
+   public void testUnpackTopLevel() throws Throwable
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile original;
+      VirtualFile replacement;
+
+      original = vfs.findChild("level1.zip");
+      replacement = VFSUtils.explode(original);
+      assertReplacement(original, replacement);
+      VirtualFile parent = original.getParent();
+      VirtualFile child = parent.findChild("level1.zip");
+      assertEquals(replacement, child);
+
+      VirtualFile textOne = replacement.findChild("test1.txt");
+      testText(textOne);
+      VirtualFile two = replacement.findChild("level2.zip");
+      VirtualFile textTwo = two.findChild("test2.txt");
+      testText(textTwo);
+      VirtualFile three = two.findChild("level3.zip");
+      VirtualFile textThree = three.findChild("test3.txt");
+      testText(textThree);
+   }
+
+   public void testUnpack2ndLevel() throws Throwable
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile original;
+      VirtualFile replacement;
+
+      original = vfs.findChild("level1.zip/level2.zip");
+      replacement = VFSUtils.unpack(original);
+      assertReplacement(original, replacement);
+      VirtualFile parent = original.getParent();
+      VirtualFile child = parent.findChild("level2.zip");
+      //assertEquals(replacement, child);
+      assertEquals(replacement.toURI(), child.toURI());
+
+      VirtualFile textTwo = replacement.findChild("test2.txt");
+      testText(textTwo);
+      VirtualFile three = replacement.findChild("level3.zip");
+      VirtualFile textThree = three.findChild("test3.txt");
+      testText(textThree);
+   }
+
+   public void testUnpackDeepLevel() throws Throwable
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+      VirtualFile original;
+      VirtualFile replacement;
+
+      original = vfs.findChild("level1.zip/level2.zip/level3.zip");
+      replacement = VFSUtils.unpack(original);
+      assertReplacement(original, replacement);
+      VirtualFile parent = original.getParent();
+      VirtualFile child = parent.findChild("level3.zip");
+      //assertEquals(replacement, child);
+      assertEquals(replacement.toURI(), child.toURI());
+
+      VirtualFile textThree = replacement.findChild("test3.txt");
+      testText(textThree);
+   }
+
+   protected void assertReplacement(VirtualFile original, VirtualFile replacement) throws Exception
+   {
+      assertEquals(original.getName(), replacement.getName());
+      // when mounting via DelegatingHandler, getPathName changes because VFSContext changes
+      //assertEquals(original.getPathName(), replacement.getPathName());
+      
+      // it's a directory
+      assertEquals(0, replacement.getSize());
+      assertEquals(original.exists(), replacement.exists());
+      assertEquals(original.isLeaf(), replacement.isLeaf());
+      assertEquals(original.isHidden(), replacement.isHidden());
+      assertEquals(original.getParent(), replacement.getParent());
+   }
+
+   protected void testText(VirtualFile file) throws Exception
+   {
+      InputStream in = file.openStream();
+      try
+      {
+         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+         String line;
+         while ((line = reader.readLine()) != null)
+         {
+            assertEquals("Some test.", line);
+         }
+      }
+      finally
+      {
+         in.close();
+      }
+   }
+}
\ No newline at end of file




More information about the jboss-cvs-commits mailing list