[jboss-cvs] JBossAS SVN: r57736 - in projects/microcontainer/trunk/container/src: main/org/jboss/virtual/plugins/context/jar tests/org/jboss/test/virtual/test

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Oct 19 15:08:23 EDT 2006


Author: scott.stark at jboss.org
Date: 2006-10-19 15:08:17 -0400 (Thu, 19 Oct 2006)
New Revision: 57736

Added:
   projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java
Modified:
   projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/AbstractJarHandler.java
   projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java
   projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java
   projects/microcontainer/trunk/container/src/tests/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
Log:
Fix the handling of jars that only have file entries

Modified: projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/AbstractJarHandler.java
===================================================================
--- projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/AbstractJarHandler.java	2006-10-19 18:57:29 UTC (rev 57735)
+++ projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/AbstractJarHandler.java	2006-10-19 19:08:17 UTC (rev 57736)
@@ -40,6 +40,7 @@
 
 import org.jboss.virtual.plugins.context.AbstractURLHandler;
 import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.plugins.vfs.helpers.PathTokenizer;
 import org.jboss.virtual.spi.VFSContext;
 import org.jboss.virtual.spi.VirtualFileHandler;
 
@@ -111,8 +112,10 @@
     */
    protected void initJarFile(JarFile jarFile) throws IOException
    {
+      /* This cannot be checked because of serialization
       if (this.jar != null)
          throw new IllegalStateException("jarFile has already been set");
+      */
 
       this.jar = jarFile;
 
@@ -163,6 +166,11 @@
                // Need to include the slash in the name to match the JarEntry.name
                String parentName = name.substring(0, slash+1);
                parent = parentMap.get(parentName);
+               if( parent == null )
+               {
+                  // Build up the parent(s) 
+                  parent = buildParents(parentName, parentMap, entry);
+               }
             }
             // Get the entry name without any directory '/' ending
             int start = slash+1;
@@ -187,10 +195,92 @@
                JarEntryHandler ehandler = (JarEntryHandler) parent;
                ehandler.addChild(handler);
             }
+            else if( parent instanceof SynthenticDirEntryHandler )
+            {
+               // This is a child of the jar entry handler
+               SynthenticDirEntryHandler ehandler = (SynthenticDirEntryHandler) parent;
+               ehandler.addChild(handler);
+            }
          }
       }
    }
 
+   /**
+    * Create any missing parents.
+    * 
+    * @param parentName full vfs path name of parent
+    * @param parentMap initJarFile parentMap
+    * @param entry JarEntry missing a parent
+    * @return the VirtualFileHandler for the parent
+    * @throws IOException
+    */
+   protected VirtualFileHandler buildParents(String parentName,
+         Map<String, VirtualFileHandler> parentMap, JarEntry entry)
+      throws IOException
+   {
+      VirtualFileHandler parent = this;
+      String[] paths = PathTokenizer.getTokens(parentName);
+      StringBuilder pathName = new StringBuilder();
+      for(String path : paths)
+      {
+         VirtualFileHandler next = null;
+         pathName.append(path);
+         pathName.append('/');
+         try
+         {
+            next = parent.findChild(path);
+         }
+         catch (IOException e)
+         {
+            // Create a synthetic parent
+            URL url = getURL(parent, path);
+            next = new SynthenticDirEntryHandler(getVFSContext(), parent, path,
+                  entry.getTime(), url);
+            parentMap.put(pathName.toString(), next);
+            if( parent == this )
+            {
+               // This is an immeadiate child of the jar handler
+               entries.add(next);
+               entryMap.put(path, next);
+            }
+            else if( parent instanceof JarEntryHandler )
+            {
+               // This is a child of the jar entry handler
+               JarEntryHandler ehandler = (JarEntryHandler) parent;
+               ehandler.addChild(next);
+            }
+            else if( parent instanceof SynthenticDirEntryHandler )
+            {
+               // This is a child of the jar entry handler
+               SynthenticDirEntryHandler ehandler = (SynthenticDirEntryHandler) parent;
+               ehandler.addChild(next);
+            }
+         }
+         parent = next;
+      }
+      return parent;
+   }
+
+   protected URL getURL(VirtualFileHandler parent, String path)
+      throws MalformedURLException
+   {
+      StringBuilder buffer = new StringBuilder();
+      try
+      {
+         buffer.append(parent.toURL());
+         if (buffer.charAt(buffer.length()-1) != '/')
+            buffer.append('/');
+         buffer.append(path);
+      }
+      catch(URISyntaxException e)
+      {
+         // Should not happen
+         throw new MalformedURLException(e.getMessage());
+      }
+      URL url = new URL(buffer.toString());
+      return url;
+   }
+
    protected void doClose()
    {
       /* TODO Figure out why this breaks things randomly
@@ -256,20 +346,7 @@
 
       // Question: Why doesn't this work properly?
       // URL url = new URL(parent.toURL(), entry.getName());
-      StringBuilder buffer = new StringBuilder();
-      try
-      {
-         buffer.append(parent.toURI());
-      }
-      catch(URISyntaxException e)
-      {
-         // Should not happen
-         throw new MalformedURLException(e.getMessage());
-      }
-      if (buffer.charAt(buffer.length()-1) != '/')
-         buffer.append('/');
-      buffer.append(entryName);
-      URL url = new URL(buffer.toString());
+      URL url = getURL(parent, entryName);
 
       VFSContext context = parent.getVFSContext();
 
@@ -309,8 +386,8 @@
       if( conn instanceof JarURLConnection )
       {
          JarURLConnection jconn = (JarURLConnection) conn;
-         JarFile jarFile = jconn.getJarFile();
-         initJarFile(jarFile);
+         jar = jconn.getJarFile();
+         // initJarFile(jar) must be called by subclasses readObject
       }
       else
       {

Modified: projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java
===================================================================
--- projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	2006-10-19 18:57:29 UTC (rev 57735)
+++ projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/JarEntryHandler.java	2006-10-19 19:08:17 UTC (rev 57736)
@@ -153,8 +153,13 @@
       return super.structuredFindChild(path);
    }
 
+   /**
+    * TODO: synchronization on lazy entryMap creation
+    */
    public VirtualFileHandler createChildHandler(String name) throws IOException
    {
+      if( entryChildren == null )
+         throw new FileNotFoundException(this+" has no children");
       if( entryMap == null )
       {
          entryMap = new HashMap<String, VirtualFileHandler>();

Modified: projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java
===================================================================
--- projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	2006-10-19 18:57:29 UTC (rev 57735)
+++ projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/NestedJarHandler.java	2006-10-19 19:08:17 UTC (rev 57736)
@@ -25,9 +25,13 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
@@ -38,6 +42,7 @@
  * Nested Jar Handler.
  * 
  * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @author Scott.Stark at jboss.org
  * @version $Revision: 1.1 $
  */
 public class NestedJarHandler extends AbstractJarHandler
@@ -106,7 +111,9 @@
     * @throws IOException for an error accessing the file system
     * @throws IllegalArgumentException for a null context, url or vfsPath
     */
-   public NestedJarHandler(VFSContext context, VirtualFileHandler parent, JarFile parentJar, JarEntry entry, URL url) throws IOException
+   public NestedJarHandler(VFSContext context, VirtualFileHandler parent,
+         JarFile parentJar, JarEntry entry, URL url)
+      throws IOException
    {
       super(context, parent, url, getEntryName(entry));
 
@@ -163,4 +170,25 @@
    {
       return temp.toURL();
    }
+
+   /**
+    * Restore the jar file from the parent jar and entry name
+    * 
+    * @param in
+    * @throws IOException
+    * @throws ClassNotFoundException
+    */
+   private void readObject(ObjectInputStream in)
+      throws IOException, ClassNotFoundException
+   {
+      JarFile parentJar = super.getJar();
+      // Initialize the transient values
+      entry = parentJar.getJarEntry(getName());
+      temp = File.createTempFile("nestedjar", null);
+      temp.deleteOnExit();
+      createTempJar(temp, parentJar, entry);
+      // Initial the parent jar entries
+      super.initJarFile(parentJar);
+   }
+
 }

Added: projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java
===================================================================
--- projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	2006-10-19 18:57:29 UTC (rev 57735)
+++ projects/microcontainer/trunk/container/src/main/org/jboss/virtual/plugins/context/jar/SynthenticDirEntryHandler.java	2006-10-19 19:08:17 UTC (rev 57736)
@@ -0,0 +1,148 @@
+/*
+* 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.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+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.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
+{
+   /** serialVersionUID */
+   private static final long serialVersionUID = 1L;
+
+   /** The jar file */
+   private long lastModified;
+   private transient 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);
+      this.lastModified = lastModified;
+   }
+
+   /**
+    * Add a child to an entry
+    * @param child
+    */
+   public void addChild(VirtualFileHandler child)
+   {
+      if( entryChildren == null )
+         entryChildren = new ArrayList<VirtualFileHandler>();
+      entryChildren.add(child);
+   }
+
+   @Override
+   public long getLastModified()
+   {
+      return lastModified;
+   }
+
+   @Override
+   public long getSize()
+   {
+      return 0;
+   }
+
+   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();
+      List<VirtualFileHandler> children = entryChildren;
+      if( entryChildren == null )
+         children = Collections.emptyList();
+      return children;
+   }
+
+   public VirtualFileHandler findChild(String path) throws IOException
+   {
+      return super.structuredFindChild(path);
+   }
+
+   /**
+    * TODO: synchronization on lazy entryMap creation
+    */
+   public VirtualFileHandler createChildHandler(String name) throws IOException
+   {
+      if( entryChildren == null )
+         throw new FileNotFoundException(this+" has no children");
+      if( entryMap == null )
+      {
+         entryMap = new HashMap<String, VirtualFileHandler>();
+         for(VirtualFileHandler child : entryChildren)
+            entryMap.put(child.getName(), child);
+      }
+      VirtualFileHandler child = entryMap.get(name);
+      if( child == null )
+         throw new FileNotFoundException(this+" has no child: "+name);
+      return child;
+   }
+
+}

Modified: projects/microcontainer/trunk/container/src/tests/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
===================================================================
--- projects/microcontainer/trunk/container/src/tests/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	2006-10-19 18:57:29 UTC (rev 57735)
+++ projects/microcontainer/trunk/container/src/tests/org/jboss/test/virtual/test/FileVFSUnitTestCase.java	2006-10-19 19:08:17 UTC (rev 57736)
@@ -115,8 +115,8 @@
       InputStream mfIS = mfe1.openStream();
       Manifest mf = new Manifest(mfIS);
       Attributes mainAttrs = mf.getMainAttributes();
-      String version = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar1", version);
+      String title1 = mainAttrs.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar1", title1);
       mfIS.close();
       njfs.close();
 
@@ -132,8 +132,8 @@
       InputStream mf2IS = mfe2.openStream();
       Manifest mf2 = new Manifest(mf2IS);
       Attributes mainAttrs2 = mf2.getMainAttributes();
-      String version2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
-      assertEquals("jar2", version2);
+      String title2 = mainAttrs2.getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals("jar2", title2);
       mf2IS.close();
       njfs2.close();
    }
@@ -379,6 +379,87 @@
    }
 
    /**
+    * Test a scan of the jar1-filesonly.jar vfs to locate all .class files
+    * @throws Exception
+    */
+   public void testClassScanFilesonly()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test/jar1-filesonly.jar");
+      VFS vfs = VFS.getVFS(rootURL);
+   
+      HashSet<String> expectedClasses = new HashSet<String>();
+      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1.class");
+      expectedClasses.add("org/jboss/test/vfs/support/jar1/ClassInJar1$InnerClass.class");
+      super.enableTrace("org.jboss.virtual.plugins.vfs.helpers.SuffixMatchFilter");
+      SuffixMatchFilter classVisitor = new SuffixMatchFilter(".class");
+      List<VirtualFile> classes = vfs.getChildren(classVisitor);
+      int count = 0;
+      for (VirtualFile cf : classes)
+      {
+         String path = cf.getPathName();
+         if( path.endsWith(".class") )
+         {
+            assertTrue(path, expectedClasses.contains(path));
+            count ++;
+         }
+      }
+      assertEquals("There were 2 classes", 2, count);
+
+      // Make sure we can walk path-wise to the class
+      VirtualFile jar1 = vfs.getRoot();
+      VirtualFile parent = jar1;
+      String className = "org/jboss/test/vfs/support/jar1/ClassInJar1.class";
+      VirtualFile ClassInJar1 = vfs.findChild(className);
+      String[] paths = className.split("/");
+      StringBuilder vfsPath = new StringBuilder();
+      for(String path : paths)
+      {
+         vfsPath.append(path);
+         VirtualFile vf = parent.findChild(path);
+         if( path.equals("ClassInJar1.class") )
+            assertEquals("ClassInJar1.class", ClassInJar1, vf);
+         else
+         {
+            assertEquals("vfsPath", vfsPath.toString(), vf.getPathName());
+            assertEquals("lastModified", ClassInJar1.getLastModified(), vf.getLastModified());
+         }
+         vfsPath.append('/');
+         parent = vf;
+      }
+   }
+
+   /**
+    * Test access of directories in a jar that only stores files
+    * @throws Exception
+    */
+   public void testFilesOnlyJar()
+      throws Exception
+   {
+      URL rootURL = getResource("/vfs/test");
+      VFS vfs = VFS.getVFS(rootURL);
+
+      VirtualFile jar = vfs.findChild("jar1-filesonly.jar");
+      VirtualFile metadataLocation = jar.findChild("META-INF");
+      assertNotNull(metadataLocation);
+      VirtualFile mfFile = metadataLocation.findChild("MANIFEST.MF");
+      assertNotNull(mfFile);
+      InputStream is = mfFile.openStream();
+      Manifest mf = new Manifest(is);
+      mfFile.close();
+      String title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
+
+      // Retry starting from the jar root
+      mfFile = jar.findChild("META-INF/MANIFEST.MF");
+      is = mfFile.openStream();
+      mf = new Manifest(is);
+      mfFile.close();
+      title = mf.getMainAttributes().getValue(Attributes.Name.SPECIFICATION_TITLE);
+      assertEquals(Attributes.Name.SPECIFICATION_TITLE.toString(), "jar1-filesonly", title);
+   }
+
+   /**
     * Test the serialization of VirtualFiles
     * @throws Exception
     */




More information about the jboss-cvs-commits mailing list