[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