[jboss-cvs] JBossAS SVN: r72878 - in projects/vfs/branches/jar-alter-work/src: main/java/org/jboss/virtual/plugins/context/file and 5 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Apr 29 18:30:10 EDT 2008


Author: mstruk
Date: 2008-04-29 18:30:10 -0400 (Tue, 29 Apr 2008)
New Revision: 72878

Added:
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java
   projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java
   projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
Modified:
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
   projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/spi/VFSContext.java
Log:
Alternative implementation of jar vfs - initial commit

Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2008-04-29 22:26:48 UTC (rev 72877)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -59,6 +59,9 @@
    /** Options associated with the root URL */
    private Map<String, String> rootOptions;
 
+   /** Root's peer within another context */
+   private VirtualFileHandler rootPeer;
+
    /**
     * Create a new AbstractVFSContext.
     * 
@@ -98,6 +101,16 @@
       return rootURI;
    }
 
+   public void setRootPeer(VirtualFileHandler handler)
+   {
+      this.rootPeer = handler;
+   }
+
+   public VirtualFileHandler getRootPeer()
+   {
+      return rootPeer;
+   }
+
    protected void addOption(String key, String value)
    {
       rootOptions.put(key, value);
@@ -124,6 +137,30 @@
       return parent.getChild(path);
    }
 
+   public URL getChildURL(VirtualFileHandler parent, String name) throws IOException
+   {
+      StringBuilder urlStr = new StringBuilder(256);
+      urlStr.append(getRootURI().toString());
+      if(parent != null)
+      {
+         String pPathName = null;
+         if(parent instanceof AbstractVirtualFileHandler)
+            pPathName = ((AbstractVirtualFileHandler)parent).getLocalPathName();
+         else
+            pPathName = parent.getPathName();
+
+         if(pPathName.length() != 0)
+            urlStr.append("/").append(pPathName);
+
+         if (urlStr.charAt( urlStr.length()-1) != '/')
+            urlStr.append("/");
+
+         urlStr.append(name);
+      }
+
+      return new URL(urlStr.toString());
+   }
+
    public void visit(VirtualFileHandler handler, VirtualFileHandlerVisitor visitor) throws IOException
    {
       if (handler == null)
@@ -204,7 +241,10 @@
          {
             try
             {
-               visit(child, visitor, false, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
+               if (handler instanceof DelegatingHandler)
+                  child.getVFSContext().visit(child, visitor);
+               else
+                  visit(child, visitor, false, leavesOnly, ignoreErrors, includeHidden, recurseFilter);
             }
             catch (StackOverflowError e)
             {

Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-04-29 22:26:48 UTC (rev 72877)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -109,6 +109,7 @@
       this.context = context;
       this.parent = parent;
       this.name = VFSUtils.fixName(name);
+      this.vfsPath = null; // nullify possible invalid vfsPath initializations when running with debugger
    }
 
    /**
@@ -200,6 +201,29 @@
       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();
@@ -238,6 +262,10 @@
     */
    private boolean initPath(StringBuilder pathName)
    {
+      if (context.getRootPeer() != null)
+         if (initPeerPath(pathName))
+            return true;
+
       if (parent != null)
       {
          if (parent instanceof AbstractVirtualFileHandler)
@@ -255,7 +283,56 @@
       }
       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();

Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-04-29 22:26:48 UTC (rev 72877)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -50,6 +50,18 @@
    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
@@ -60,11 +72,21 @@
    public DelegatingHandler(VFSContext context, VirtualFileHandler parent, String name, VirtualFileHandler delegate)
    {
       super(context, parent, name);
-      if (delegate == null)
-         throw new IllegalArgumentException("Null delegate");
+      //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);
@@ -119,4 +141,9 @@
    {
       delegate.replaceChild(original, replacement);
    }
+
+   public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+   {
+      return delegate.toVfsUrl();
+   }
 }

Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	2008-04-29 22:26:48 UTC (rev 72877)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -33,7 +33,8 @@
 import org.jboss.virtual.VFSUtils;
 import org.jboss.virtual.VirtualFile;
 import org.jboss.virtual.plugins.context.AbstractVFSContext;
-import org.jboss.virtual.plugins.context.jar.JarHandler;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
 import org.jboss.virtual.plugins.context.jar.JarUtils;
 import org.jboss.virtual.spi.LinkInfo;
 import org.jboss.virtual.spi.VirtualFileHandler;
@@ -190,9 +191,11 @@
       {
          try
          {
-            return new JarHandler(this, parent, file, file.toURL(), name);
+            //return new JarHandler(this, parent, file, file.toURL(), name);
+            DelegatingHandler delegator = mountZipFS(parent, name, file);
+            return delegator;
          }
-         catch (IOException e)
+         catch (Exception e)
          {
             log.debug("Exception while trying to handle file (" + name + ") as a jar: " + e.getMessage());
          }
@@ -200,6 +203,23 @@
       return createVirtualFileHandler(parent, file, getFileURI(file));
    }
 
+   protected DelegatingHandler mountZipFS(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
+   {
+      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+      URL fileUrl = file.toURL();
+      URL delegatorUrl = fileUrl;
+
+      if (parent != null)
+         delegatorUrl = getChildURL(parent, name);
+
+      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl);
+
+      VirtualFileHandler handler = ctx.getRoot();
+      delegator.setDelegate(handler);
+
+      return delegator;
+   }
+   
    /**
     * Create a new virtual file handler
     * 

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,639 @@
+package org.jboss.virtual.plugins.context.zip;
+
+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;
+
+import java.io.*;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * VFSContext exposing a zip archive file as a virtual file system
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipEntryContext extends AbstractVFSContext
+{
+   static
+   {
+      deleteTmpDirContents();
+   }
+
+   /** File representing a zip archive that is virtualized with this context */
+   private File rootFile;
+
+   /** ZipFile opened around rootFile */
+   private ZipFileWrapper zipFile;
+
+   /** Entry path representing a context root */
+   private String rootEntryPath = "";
+
+   /** Auto clean signals if rootFile should be deleted after closing the context */
+   private boolean autoClean = false;
+
+   /** Entries in a hierarchy */
+   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 IOException
+    */
+   public ZipEntryContext(URL rootURL, boolean autoClean) throws URISyntaxException, IOException
+   {
+      super(fixUrl(rootURL));
+      this.autoClean = autoClean;
+      init(rootURL, null);
+   }
+
+   /**
+    * Create a new ZipEntryContext being 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 IOException
+    */
+   public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl) throws URISyntaxException, IOException
+   {
+      this(rootURL, peer, localRootUrl, false);
+   }
+
+   /**
+    * Create a new ZipEntryContext being 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(fixUrl(rootURL));
+      this.autoClean = autoClean;
+      init(localRootUrl, peer);
+   }
+
+   private void init(URL localRootURL, VirtualFileHandler peer) throws IOException, URISyntaxException
+   {
+      initFileAndPath(localRootURL);
+
+      if(!rootFile.isFile())
+         throw new RuntimeException("File not found: " + rootFile);
+
+      //try
+      //{
+         zipFile = new ZipFileWrapper(rootFile);
+      //}
+      //catch(Exception ex)
+      //{
+      //   throw new RuntimeException("Failed to open the file as zip: " + rootFile, ex);
+      //}
+
+      setRootPeer(peer);
+
+      String name = getRootURI().toString();   // rootFile.getName()
+      int toPos = name.length();
+      if(name.length() != 0 && name.charAt(name.length()-1) == '/')
+         toPos --;
+
+      int namePos = name.lastIndexOf("/", toPos-1);
+      name = name.substring(namePos+1, toPos);
+
+      if(name.length() != 0 && name.charAt(name.length()-1) == '!')
+         name = name.substring(0, name.length()-1);
+
+      // init initial root that will be overwritten if it exists as ZipEntry
+      entries.put("", new EntryInfo(new ZipEntryHandler(this, null, name), null));
+
+      initEntries();
+
+      ZipEntryContextFactory.registerContext(this);
+   }
+
+   public String getName()
+   {
+      VirtualFileHandler peer = getRootPeer();
+      if (peer != null)
+         return peer.getName();
+      else
+         return rootFile.getName();
+   }
+
+
+/*
+   public URL getChildURL(AbstractVirtualFileHandler parent, String name) {
+      try
+      {
+ // --
+         StringBuilder url = new StringBuilder();
+         VirtualFileHandler peer = getRootPeer();
+         if (peer != null)
+         {
+            VFSContext peerCtx = peer.getVFSContext();
+            if (peerCtx instanceof AbstractVFSContext)
+
+               url.append( ((AbstractVirtualFileHandler) peer).getGlobalChildURI() );
+         }
+         String parentPath = parent.getLocalPathName();
+         url.append(parentPath);
+         if(!"".equals(parentPath))
+            url.append("/");
+         url.append(name);
+ // --
+
+         StringBuilder urlStr = new StringBuilder(250);
+         urlStr.append(getRootURI().toString());
+         if(parent != null)
+         {
+            String pPathName = parent.getLocalPathName();
+            if(pPathName.length() != 0)
+               urlStr.append("/").append(pPathName);
+
+            urlStr.append("/").append(name);
+         }
+
+         return new URL(urlStr.toString());
+      }
+      catch(Exception ex)
+      {
+         throw new IllegalArgumentException("Name could not be converted to URL: " + name, ex);
+      }
+   }
+*/
+
+   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>();
+      ZipFile zFile = zipFile.acquire();
+      try
+      {
+         Enumeration<? extends ZipEntry> zipEntries = zFile.entries();
+         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() && JarUtils.isArchive(ent.getName()))
+            {
+               // extract it to temp dir
+               File dest = new File(getTempDir() + "/" + getTempFileName(ent.getName()));
+               dest.getParentFile().mkdirs();  // ensure parent exists
+               InputStream is = zipFile.openStream(ent);
+               OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
+               copyStreamAndClose(is, os);
+
+               // mount FS
+               DelegatingHandler delegator = mountZipFS(parent, name, dest);
+
+               entries.put(delegator.getLocalPathName(), new EntryInfo(delegator, ent));
+               addChild(parent, delegator);
+            }
+            else
+            {
+               ZipEntryHandler wrapper = new ZipEntryHandler(this, parent, name);
+               entries.put(wrapper.getLocalPathName(), new EntryInfo(wrapper, ent));
+            }
+
+         }
+      }
+      finally
+      {
+         zipFile.release();
+      }
+
+   }
+
+   protected DelegatingHandler mountZipFS(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
+   {
+      DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+      URL fileUrl = file.toURL();
+      URL delegatorUrl = fileUrl;
+
+      if (parent != null)
+         delegatorUrl = getChildURL(parent, name);
+         //delegatorUrl = new URL(VFSUtils.getChildURLString(parent.toURL(), name));
+
+
+      ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl, true);
+
+      VirtualFileHandler handler = ctx.getRoot();
+      delegator.setDelegate(handler);
+
+      return delegator;
+   }
+
+   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]);
+      EntryInfo ei = new EntryInfo(handler, null);
+      entries.put(parentPath, ei);
+      return ei;
+   }
+
+   private void initFileAndPath(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 += "/";
+      }
+
+      try
+      {
+         // find where schema ends - all schemas when you have wrapping ...
+         pos= zipPath.indexOf(":/");
+         filePath = "file:" + zipPath.substring(pos+1);
+         rootFile = new File(new URI(filePath));
+         if (autoClean)
+            rootFile.deleteOnExit();
+      }
+      catch(Exception ex)
+      {
+         throw new RuntimeException("ASSERTION ERROR - Could not create URI: " + filePath, ex);
+      }
+   }
+
+   public VirtualFileHandler getRoot() throws IOException
+   {
+      return entries.get("").handler;
+   }
+
+   private synchronized void checkIfModified()
+   {
+      // our rootFile may be a derivative - the extracted insides of another archive
+      // if RootContextInfo is available - delegate to it
+      // otherwise work on the file directly
+      if (zipFile.hasBeenModified())
+      {
+         EntryInfo rootInfo = entries.get("");
+         entries = new ConcurrentHashMap<String, EntryInfo>();
+         entries.put("", rootInfo);
+
+         if (zipFile.exists())
+         {
+            try
+            {
+               initEntries();
+            }
+            catch(Exception ex)
+            {
+               log.warn("Failed to reinitialize context: " + getRootURI());
+            }
+         }
+      }
+
+   }
+
+   public VirtualFileHandler getChild(ZipEntryHandler parent, String name)
+   {
+      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
+   {
+      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);
+            
+            List<AbstractVirtualFileHandler> children = parentEntry.getChildren();
+            return Collections.unmodifiableList(new LinkedList<VirtualFileHandler>(children));
+         }
+      }
+      return Collections.emptyList();
+   }
+
+
+   public long getLastModified(ZipEntryHandler handler)
+   {
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null)
+         return 0;
+
+      if(ei.entry == null) {
+         return rootFile.lastModified();
+      }
+
+      return ei.entry.getTime();
+   }
+
+   public long getSize(ZipEntryHandler 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 rootFile.length();
+         else
+            return 0;
+      }
+
+      return ei.entry.getSize();
+   }
+
+   public boolean exists(ZipEntryHandler handler)
+   {
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+      if(ei == null)
+         return false;
+
+      return true;
+   }
+
+   public boolean isLeaf(ZipEntryHandler 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
+   {
+      checkIfModified();
+      EntryInfo ei = entries.get(handler.getLocalPathName());
+
+      if (ei == null)
+      {
+         String uriStr = "";
+         try
+         {
+            uriStr = handler.toURI().toString();
+         }
+         catch(Exception ex)
+         {
+            throw new RuntimeException("ASSERTION ERROR - uri generation failed for ZipEntryHandler: " + handler);
+         }
+         throw new FileNotFoundException(uriStr);
+
+      }
+
+      if(ei.entry == null)
+      {
+         return new FileInputStream(rootFile); 
+      }
+      
+      return zipFile.openStream(ei.entry);
+   }
+
+   public void addChild(AbstractVirtualFileHandler parent, AbstractVirtualFileHandler child)
+   {
+      EntryInfo parentEntry = entries.get(parent.getLocalPathName());
+      if (parentEntry != null)
+         parentEntry.getChildren().add(child);
+      else throw new RuntimeException("Parent does not exist: " + parent);
+   }
+
+
+
+   protected void finalize()
+   {
+      try
+      {
+         zipFile.close();
+         if (autoClean)
+            rootFile.delete();
+      }
+      catch (Exception ex)
+      {
+         // ignore
+      }
+   }
+
+
+   /**
+    *  Internal data structure, holding ZipEntries and child handlers for every handler in this context
+    */
+   static class EntryInfo
+   {
+      AbstractVirtualFileHandler handler;
+      ZipEntry entry;
+      List<AbstractVirtualFileHandler> children;
+
+      EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
+      {
+         this.handler = handler;
+         this.entry = entry;
+      }
+
+      public synchronized List<AbstractVirtualFileHandler> getChildren()
+      {
+         if (children == null)
+            children = new LinkedList<AbstractVirtualFileHandler>();
+
+         return children;
+      }
+   }
+
+
+   //
+   //   Helper methods
+   //
+
+   private static URL fixUrl(URL rootURL) throws MalformedURLException
+   {
+      if (!"vfszip".equals(rootURL.getProtocol()))
+      {
+         String url = rootURL.toString();
+         int pos = url.indexOf(":/");
+         if (pos != -1)
+            url = url.substring(pos);
+
+         return new URL("vfszip" + url);
+      }
+      return rootURL;
+   }
+
+   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;
+   }
+
+   private 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 ex)
+            {
+               // ignore
+            }
+         }
+         os.close();
+      }
+   }
+
+
+   // TODO: the following two methods are a quick and dirty strategy for temp file name and path
+   private static String getTempFileName(String name)
+   {
+      int delim = name.lastIndexOf("/");
+      if (delim != -1)
+         name = name.substring(delim+1);
+      return UUID.randomUUID().toString() + "_" + name;
+   }
+
+   private static String getTempDir()
+   {
+      File dir = new File(System.getProperty("jboss.server.temp.dir"), "vfs");
+      //dir.mkdirs();
+      return dir.toString();
+   }
+
+   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 ex)
+      {
+        // ignore
+      }
+
+   }
+
+}

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,97 @@
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.virtual.plugins.context.AbstractContextFactory;
+import org.jboss.virtual.spi.VFSContext;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * ContextFactory that keeps track of ZipEntryContexts
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipEntryContextFactory extends AbstractContextFactory
+{
+
+   public static Map<String, ZipEntryContext> ctxCache = new ConcurrentHashMap<String, ZipEntryContext>();
+
+   private static ZipEntryContextFactory instance = new ZipEntryContextFactory();
+
+   public ZipEntryContextFactory()
+   {
+      super("jar", "vfsjar", "zip", "vfszip");
+   }
+
+   public VFSContext getVFS(URI rootURI) throws IOException
+   {
+      return getVFS(rootURI.toURL());
+   }
+
+   public VFSContext getVFS(URL rootURL) throws IOException
+   {
+      String key = rootURL.toString();
+      int cutPos = key.indexOf(":/");
+      key = key.substring(cutPos+1);
+
+      String longestMatchingKey = null;
+      ZipEntryContext longestMatchingCtx = null;
+
+      for(Map.Entry<String, ZipEntryContext> ent : ctxCache.entrySet())
+      {
+         if(key.startsWith(ent.getKey()))
+         {
+            if(longestMatchingCtx == null || ent.getKey().length() > longestMatchingKey.length())
+            {
+               longestMatchingKey = ent.getKey();
+               longestMatchingCtx = ent.getValue();
+            }
+         }
+      }
+
+      ZipEntryContext ctx = null;
+      if(longestMatchingCtx != null)
+         ctx = longestMatchingCtx;
+
+      if(ctx != null)
+         return ctx;
+
+      try
+      {
+         ctx = new ZipEntryContext(rootURL);
+      }
+      catch(URISyntaxException ex)
+      {
+         MalformedURLException e = new MalformedURLException("Failed to convert URL to URI: " + rootURL);
+         e.initCause(ex);
+         throw e;
+      }
+
+      // no need to put a newly created context into ctxCache
+      // it's constructor does that by calling registerContext
+      
+      return ctx;
+   }
+
+   public static ZipEntryContextFactory getInstance()
+   {
+      return instance;
+   }
+
+   public static void registerContext(ZipEntryContext ctx)
+   {
+      String key = ctx.getRootURI().toString();
+      int cutPos = key.indexOf(":/");
+      key = key.substring(cutPos+1);
+      if("".equals(key))
+         throw new RuntimeException("Derived key for ZipEntryContext registration is empty: " + ctx.getRootURI());
+      ctxCache.put(key, ctx);
+   }
+}

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,122 @@
+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
+    */
+   public ZipEntryHandler(ZipEntryContext context, AbstractVirtualFileHandler parent, String name) throws IOException
+   {
+      super(context, parent, name);
+
+      url = context.getChildURL(parent, name);
+
+      String vfsUrl = url.toString();
+      int pos = vfsUrl.indexOf(":/");
+      vfsUrl = "vfszip:" + vfsUrl.substring(pos+1);
+      try
+      {
+         setVfsUrl(new URL(vfsUrl));
+      }
+      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
+   {
+      return getZipEntryContext().isLeaf(this);
+   }
+
+   public boolean isHidden() throws IOException
+   {
+      return false;
+   }
+
+   public InputStream openStream() throws IOException
+   {
+      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);
+   }
+
+   private ZipEntryContext getZipEntryContext()
+   {
+      return ((ZipEntryContext) getVFSContext());
+   }
+
+
+}

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,143 @@
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+
+/**
+ * InputStream that wraps an InputStream retrieved from ZipFile.getInputStream(entry)
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipEntryInputStream extends InputStream
+{
+   private InputStream delegate;
+
+   private ZipFileWrapper zipWrapper;
+
+   private boolean closed;
+
+   ZipEntryInputStream(ZipFileWrapper zipWrapper, InputStream is) throws IOException
+   {
+      this.zipWrapper = zipWrapper;
+      delegate = is;
+   }
+
+   private void streamClosed(boolean doClose)
+   {
+      if (closed == false && doClose)
+      {
+         closed = true;
+         zipWrapper.release();
+      }
+   }
+
+   public int read() throws IOException
+   {
+      int rc = -1;
+      try
+      {
+         rc = delegate.read();
+         return rc;
+      }
+      finally
+      {
+         streamClosed(rc < 0);
+      }
+   }
+
+   public int read(byte buf[]) throws IOException
+   {
+      int rc = -1;
+      try
+      {
+         rc = delegate.read(buf);
+         return rc;
+      }
+      finally
+      {
+         streamClosed(rc < 0);
+      }
+   }
+
+   public int read(byte buf[], int off, int len) throws IOException
+   {
+      int rc = -1;
+      try
+      {
+         rc = delegate.read(buf, off, len);
+         return rc;
+      }
+      finally
+      {
+         streamClosed(rc < 0);
+      }
+   }
+
+   public synchronized void reset() throws IOException
+   {
+      boolean ok = false;
+      try
+      {
+         delegate.reset();
+         ok = true;
+      }
+      finally
+      {
+         streamClosed(ok == false);
+      }
+   }
+
+   public synchronized void mark(int readlimit)
+   {
+      boolean ok = false;
+      try
+      {
+         delegate.mark(readlimit);
+         ok = true;
+      }
+      finally
+      {
+         streamClosed(ok == false);
+      }
+   }
+
+   public int available() throws IOException
+   {
+      boolean ok = false;
+      try
+      {
+         int ret = delegate.available();
+         ok = true;
+         return ret;
+      }
+      finally
+      {
+         streamClosed(ok == false);
+      }
+   }
+
+   public long skip(long n) throws IOException
+   {
+      boolean ok = false;
+      try
+      {
+         long ret = delegate.skip(n);
+         ok = true;
+         return ret;
+      }
+      finally
+      {
+         streamClosed(ok == false);
+      }
+   }
+
+   public void close() throws IOException
+   {
+      streamClosed(true);
+      super.close();
+   }
+
+}

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,125 @@
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.logging.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+/**
+ * ZipFileWrapper releases and reacquires an underlying ZipFile as necessary
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipFileWrapper
+{
+   private static final Logger log = Logger.getLogger(ZipFileWrapper.class);
+
+   private File file;
+
+   private ZipFile zipFile;
+
+   private long lastUsed;
+
+   private long lastModified;
+
+   private long lastChecked;
+
+   private int refCount = 0;
+
+   public ZipFileWrapper(File archive)
+   {
+      file = archive;
+      lastModified = file.lastModified();
+   }
+
+   boolean hasBeenModified()
+   {
+      long now = System.currentTimeMillis();
+      if (now - lastChecked < 1000)
+         return false;
+
+      lastChecked = now;
+      long lm = file.lastModified();
+      if (lm != lastModified)
+      {
+         lastModified = lm;
+         return true;
+      }
+
+      return false;
+   }
+
+   boolean exists()
+   {
+      return file.isFile();
+   }
+
+   private ZipFile ensureZipFile() throws IOException
+   {
+      if (zipFile == null)
+         zipFile = new ZipFile(file);
+
+      return zipFile;
+   }
+
+   private void closeZipFile() throws IOException
+   {
+      if (zipFile != null)
+      {
+         ZipFile zf = zipFile;
+         zipFile = null;
+         zf.close();
+      }
+   }
+
+   synchronized ZipEntryInputStream openStream(ZipEntry ent) throws IOException
+   {
+      ensureZipFile();
+      InputStream is = zipFile.getInputStream(ent);
+      ZipEntryInputStream zis = new ZipEntryInputStream(this, is);
+      refCount++;
+      lastUsed = System.currentTimeMillis();
+      return zis;
+   }
+
+
+   synchronized void release()
+   {
+      refCount--;
+      if (refCount <= 0)
+      {
+         try
+         {
+            lastUsed = System.currentTimeMillis();
+            closeZipFile();
+         }
+         catch(Exception ex)
+         {
+            log.warn("Failed to release file: " + file);
+         }
+      }
+   }
+
+   synchronized ZipFile acquire() throws IOException
+   {
+      ZipFile ret = ensureZipFile();
+      refCount++;
+      return ret;
+   }
+
+   void close()
+   {
+      try
+      {
+         closeZipFile();
+      }
+      catch(Exception ex)
+      {
+         log.warn("Failed to release file: " + file);
+      }
+   }
+}

Added: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,37 @@
+package org.jboss.virtual.protocol.vfszip;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContextFactory;
+import org.jboss.virtual.plugins.vfs.VirtualFileURLConnection;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/**
+ * URLStreamHandler for VFS
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class Handler extends URLStreamHandler
+{
+   protected URLConnection openConnection(URL u) throws IOException
+   {
+      String url = u.toString();
+      ZipEntryContext ctx = (ZipEntryContext) ZipEntryContextFactory.getInstance().getVFS(u);
+      if (ctx == null)
+         throw new IOException("vfs does not exist: " + url);
+
+      String rootPath = ctx.getRootURI().getPath();
+      String entryPath = u.getFile().substring(rootPath.length());
+      VirtualFile vf = ctx.getChild(ctx.getRoot(), entryPath).getVirtualFile();
+      if (vf == null)
+         throw new IOException("vfs does not exist: " + url);
+
+      return new VirtualFileURLConnection(u, vf);
+   }
+}

Modified: projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/spi/VFSContext.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/spi/VFSContext.java	2008-04-29 22:26:48 UTC (rev 72877)
+++ projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/spi/VFSContext.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -68,6 +68,14 @@
    VirtualFileHandler getRoot() throws IOException;
 
    /**
+    * Return the peer representing the root of this context within another context.
+    * Used when mounting contexts within other contexts
+    *
+    * @return the root peer
+    */
+   VirtualFileHandler getRootPeer();
+
+   /**
     * Get the context option settings
     * 
     * @return a map of the context options

Added: projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,183 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.spi.VFSContext;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.util.jar.*;
+
+/**
+ * JARVirtualFileHandlerUnitTestCase.
+ *
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ZipEntryHandlerUnitTestCase extends AbstractVirtualFileHandlerTest
+{
+   public ZipEntryHandlerUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return new TestSuite(ZipEntryHandlerUnitTestCase.class);
+   }
+
+
+
+   /*
+   public void testJarCache() throws Exception
+   {
+      // Create a test.jar with v1 in manifest
+      File testFile = new File("test.jar");
+      {
+         Manifest manifest = new Manifest();
+         manifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1");
+         manifest.getMainAttributes().putValue("test", "v1");
+         JarOutputStream out = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(testFile)), manifest);
+         out.flush();
+         out.close();
+      }
+
+      // Verify it via VFS
+      File root = new File(".");
+      {
+         VirtualFile vf = VFS.getVirtualFile(root.toURL(), "test.jar");
+//         System.err.println("lastModified = " + vf.getLastModified());
+         VirtualFile manifestFile = vf.findChild("META-INF/MANIFEST.MF");
+         Manifest manifest = new Manifest(manifestFile.openStream());
+         String actual = manifest.getMainAttributes().getValue("test");
+         assertEquals("v1", actual);
+      }
+
+      // If we don't delete, VFS will give ZIP errors (related issue?)
+      assertTrue("test file deleted: " + testFile, testFile.delete());
+
+      // Create a new test.jar with manifest v2
+      {
+         Manifest manifest = new Manifest();
+         manifest.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1");
+         manifest.getMainAttributes().putValue("test", "v2");
+         JarOutputStream out = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(testFile)), manifest);
+         out.flush();
+         out.close();
+      }
+
+      // Verify the manifest the JDK way
+      {
+         JarFile jarFile = new JarFile(testFile);
+         String actual = jarFile.getManifest().getMainAttributes().getValue("test");
+         assertEquals("JDK found the wrong manifest", "v2", actual);
+         jarFile.close();
+      }
+
+      // Verify the manifest the VFS way
+      {
+         VirtualFile vf = VFS.getVirtualFile(root.toURL(), "test.jar");
+         // Note that the modification date has not changed according to VFS
+//         System.err.println("lastModified = " + vf.getLastModified());
+//         System.err.println("modified = " + vf.hasBeenModified());
+
+         VirtualFile manifestFile = vf.findChild("META-INF/MANIFEST.MF");
+         Manifest manifest = new Manifest(manifestFile.openStream());
+         String actual = manifest.getMainAttributes().getValue("test");
+         assertEquals("VFS found the wrong manifest", "v2", actual);
+      }
+   }
+   */
+
+
+   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 ZipEntryContext(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();
+      }
+   }
+}
\ No newline at end of file

Added: projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
===================================================================
--- projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	                        (rev 0)
+++ projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java	2008-04-29 22:30:10 UTC (rev 72878)
@@ -0,0 +1,116 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.virtual.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.plugins.context.file.FileSystemContext;
+import org.jboss.virtual.plugins.context.jar.JarContext;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.spi.VFSContext;
+
+import java.net.URL;
+
+/**
+ * JARVFSContextUnitTestCase.
+ *
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision: 1.1 $
+ */
+public class ZipEntryVFSContextUnitTestCase extends AbstractVFSContextTest
+{
+   public ZipEntryVFSContextUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      VFS.init();
+      System.out.println("java.protocol.handler.pkgs: " + System.getProperty("java.protocol.handler.pkgs"));
+      return new TestSuite(ZipEntryVFSContextUnitTestCase.class);
+   }
+
+   protected VFSContext getVFSContext(String name) throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/" + name + ".jar");
+      url = JarUtils.createJarURL(url);
+      return new ZipEntryContext(url);
+   }
+
+   protected VFSContext getParentVFSContext() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/");
+      return new FileSystemContext(url);
+   }
+
+   protected String getSuffix()
+   {
+      return ".jar";
+   }
+
+   /**
+    * Was having problems with a jar entry as root of VFS.
+    *
+    * @throws Exception
+    */
+   public void testJarEntryAsRoot() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/simple.jar");
+      URL entry = new URL("jar:" + url.toString() + "!/child");
+      //entry.openStream().close();
+      ZipEntryContext context = new ZipEntryContext(entry);
+      assertEquals("child", context.getRoot().getName());
+
+      url = getResource("/vfs/test/outer.jar");
+      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
+      //entry.openStream().close();
+      context = new ZipEntryContext(entry);
+      assertEquals("jar2.jar", context.getRoot().getName());
+   }
+
+   /**
+    * Was having problems with a jar entry as root of VFS.
+    * A JarEntry that is the root of the VFS should have a VFS Path of ""
+    *
+    * @throws Exception
+    */
+   public void testPathIsEmptryForJarEntryAsRoot() throws Exception
+   {
+      URL url = getResource("/vfs/context/jar/simple.jar");
+      URL entry = new URL("jar:" + url.toString() + "!/child");
+      //entry.openStream().close();
+      ZipEntryContext context = new ZipEntryContext(entry);
+      assertEquals("child", context.getRoot().getName());
+      assertEquals("", context.getRoot().getPathName());
+
+      url = getResource("/vfs/test/outer.jar");
+      entry = new URL("jar:" + url.toString() + "!/jar2.jar ");
+      //entry.openStream().close();
+      context = new ZipEntryContext(entry);
+      assertEquals("jar2.jar", context.getRoot().getName());
+      assertEquals("", context.getRoot().getPathName());
+   }
+
+}
\ No newline at end of file




More information about the jboss-cvs-commits mailing list