[jboss-cvs] JBossAS SVN: r76996 - in projects/vfs/trunk/src: main/java/org/jboss/virtual/plugins/context/zip and 1 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Aug 12 16:51:05 EDT 2008
Author: mstruk
Date: 2008-08-12 16:51:05 -0400 (Tue, 12 Aug 2008)
New Revision: 76996
Modified:
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
Log:
JBVFS-51 Lazy initialization of zip archive content to improve performance
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java 2008-08-12 18:29:31 UTC (rev 76995)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java 2008-08-12 20:51:05 UTC (rev 76996)
@@ -164,23 +164,56 @@
return parent.getChild(path);
}
+ /**
+ * Construct a URL from a given parent and a name
+ *
+ * @param parent a parent
+ * @param name a name of the child
+ * @return URL corresponding to a child
+ * @throws IOException for any error
+ */
public URL getChildURL(VirtualFileHandler parent, String name) throws IOException
- {
- StringBuilder urlStr = new StringBuilder(256);
+ {
+ if(parent != null)
+ {
+ VFSContext parentCtx = parent.getVFSContext();
+ if (parentCtx != this)
+ {
+ if (parentCtx instanceof AbstractVFSContext)
+ {
+ return ((AbstractVFSContext) parentCtx).getChildURL(parent, name);
+ }
+ else
+ {
+ StringBuilder urlStr = new StringBuilder(512);
+ try
+ {
+ urlStr.append(parent.toURI());
+ if (urlStr.charAt( urlStr.length()-1) != '/')
+ urlStr.append("/");
+
+ urlStr.append(name);
+ return new URL(urlStr.toString());
+ }
+ catch (URISyntaxException e)
+ {
+ throw new RuntimeException("Failed to create child URL: " + parent + " + " + name, e);
+ }
+ }
+ }
+ }
+
+ StringBuilder urlStr = new StringBuilder(512);
URI rootUri = getRootURI();
urlStr.append(rootUri.getScheme())
.append(":").append(rootUri.getPath());
+
if(parent != null)
{
- String pPathName;
- if(parent instanceof AbstractVirtualFileHandler)
- pPathName = parent.getLocalPathName();
- else
- pPathName = parent.getPathName();
-
if (urlStr.charAt( urlStr.length()-1) != '/')
urlStr.append("/");
+ String pPathName = parent.getPathName();
if(pPathName.length() != 0)
urlStr.append(pPathName);
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java 2008-08-12 18:29:31 UTC (rev 76995)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java 2008-08-12 20:51:05 UTC (rev 76996)
@@ -615,7 +615,7 @@
buffer.append(System.identityHashCode(this));
buffer.append("[path=").append(getLocalPathName());
buffer.append(" context=").append(context.getRootURI());
- buffer.append(" real=").append(safeToURLString());
+ //buffer.append(" real=").append(safeToURLString());
buffer.append(']');
return buffer.toString();
}
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java 2008-08-12 18:29:31 UTC (rev 76995)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java 2008-08-12 20:51:05 UTC (rev 76996)
@@ -118,6 +118,9 @@
/** Registry of everything that zipSource contains */
private Map<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
+ /** Have zip entries been navigated yet */
+ private InitializationStatus initStatus = InitializationStatus.NOT_INITIALIZED;
+
/**
* Create a new ZipEntryContext
*
@@ -220,15 +223,10 @@
setRootPeer(peer);
- String name = getRootURI().toString();
+ String name = getRootURI().getPath().toString();
- // cut off query string
- int toPos = name.lastIndexOf("?");
- if (toPos != -1)
- name = name.substring(0, toPos);
+ int toPos = name.length();
- toPos = name.length();
-
// cut off any ending slash
if(name.length() != 0 && name.charAt(name.length()-1) == '/')
toPos --;
@@ -245,7 +243,8 @@
// if zip entry exists for rootEntryPath
entries.put("", new EntryInfo(new ZipEntryHandler(this, null, name, true), null));
- initEntries();
+ // It's lazy init now
+ //initEntries();
}
/**
@@ -476,6 +475,32 @@
}
/**
+ * Perform initialization only if it hasn't been done yet
+ */
+ private synchronized void ensureEntries()
+ {
+ if (initStatus != InitializationStatus.NOT_INITIALIZED)
+ return;
+
+ try
+ {
+ initStatus = InitializationStatus.INITIALIZING;
+ initEntries();
+ initStatus = InitializationStatus.INITIALIZED;
+ }
+ catch (Exception ex)
+ {
+ RuntimeException e = new RuntimeException("Failed to read zip file: " + zipSource, ex);
+ throw e;
+ }
+ finally
+ {
+ if (initStatus == InitializationStatus.INITIALIZING)
+ initStatus = InitializationStatus.NOT_INITIALIZED;
+ }
+ }
+
+ /**
* Mount ZipEntryContext created around extracted nested archive
*
* @param parent the parent
@@ -586,13 +611,18 @@
}
/**
- * If archive has been modified, clear <em>entries</em> and re-initialize
+ * If archive has been modified, clear <em>entries</em> and re-initialize.
+ * If not initialized yet, initialize it.
*/
private synchronized void checkIfModified()
{
// TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
- if (zipSource.hasBeenModified())
+ if (initStatus == InitializationStatus.NOT_INITIALIZED)
{
+ ensureEntries();
+ }
+ else if (initStatus == InitializationStatus.INITIALIZED && zipSource.hasBeenModified())
+ {
EntryInfo rootInfo = entries.get("");
entries = new ConcurrentHashMap<String, EntryInfo>();
entries.put("", rootInfo);
@@ -617,7 +647,7 @@
* @return root handler
* @throws IOException for any error
*/
- public VirtualFileHandler getRoot() throws IOException
+ public VirtualFileHandler getRoot()
{
return entries.get("").handler;
}
@@ -635,6 +665,7 @@
throw new IllegalArgumentException("Null parent");
checkIfModified();
+
String pathName = parent.getLocalPathName();
if("".equals(pathName))
pathName = name;
@@ -642,7 +673,6 @@
pathName = pathName + "/" + name;
EntryInfo ei = entries.get(pathName);
-
if(ei != null)
return ei.handler;
@@ -698,7 +728,8 @@
if (handler == null)
throw new IllegalArgumentException("Null handler");
- checkIfModified();
+ if (getRoot().equals(handler) == false)
+ checkIfModified();
EntryInfo ei = entries.get(handler.getLocalPathName());
if(ei == null)
return 0;
@@ -721,20 +752,15 @@
if (handler == null)
throw new IllegalArgumentException("Null handler");
+ if(getRoot().equals(handler))
+ return zipSource.getSize();
+
checkIfModified();
- String pathName = handler.getLocalPathName();
- EntryInfo ei = entries.get(pathName);
- if(ei == null)
+
+ EntryInfo ei = entries.get(handler.getLocalPathName());
+ if(ei == null || ei.entry == null)
return 0;
- if(ei.entry == null)
- {
- if(pathName.length() == 0)
- return zipSource.getSize();
- else
- return 0;
- }
-
return ei.entry.getSize();
}
@@ -749,15 +775,14 @@
if (handler == null)
throw new IllegalArgumentException("Null handler");
+ if (getRoot().equals(handler))
+ return zipSource.exists();
+
checkIfModified();
- String pathName = handler.getLocalPathName();
- EntryInfo ei = entries.get(pathName);
+ EntryInfo ei = entries.get(handler.getLocalPathName());
if(ei == null)
return false;
- if (ei.entry == null && pathName.length() == 0)
- return zipSource.exists();
-
return true;
}
@@ -772,9 +797,11 @@
if (handler == null)
throw new IllegalArgumentException("Null handler");
- checkIfModified();
+ if (getRoot().equals(handler) == false)
+ checkIfModified();
+
EntryInfo ei = entries.get(handler.getLocalPathName());
- if(ei == null || ei.entry == null)
+ if (ei == null || ei.entry == null)
return false;
return !ei.entry.isDirectory();
@@ -852,10 +879,12 @@
if (handler == null)
throw new IllegalArgumentException("Null handler");
+ if (getRoot().equals(handler))
+ return zipSource.getRootAsStream();
+
checkIfModified();
- String localPathName = handler.getLocalPathName();
- EntryInfo ei = entries.get(localPathName);
+ EntryInfo ei = entries.get(handler.getLocalPathName());
if (ei == null)
{
@@ -872,13 +901,8 @@
}
if(ei.entry == null)
- {
- if ("".equals(localPathName)) // root
- return zipSource.getRootAsStream();
- else // directory
- return new ByteArrayInputStream(new byte[0]);
- }
-
+ return new ByteArrayInputStream(new byte[0]);
+
return zipSource.openStream(ei.entry);
}
@@ -929,6 +953,7 @@
*/
public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
{
+ ensureEntries();
EntryInfo parentEntry = entries.get(parent.getLocalPathName());
if (parentEntry != null)
{
@@ -1189,4 +1214,10 @@
return Boolean.valueOf(forceString);
}
}
+
+ static enum InitializationStatus {
+ NOT_INITIALIZED,
+ INITIALIZING,
+ INITIALIZED
+ }
}
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java 2008-08-12 18:29:31 UTC (rev 76995)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java 2008-08-12 20:51:05 UTC (rev 76996)
@@ -43,8 +43,14 @@
public class ZipEntryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
{
/** The url */
- private final URL url;
+ private URL url;
+ /** isLeaf */
+ private boolean isLeaf;
+
+ /** has it been initialized yet */
+ transient private boolean initialized;
+
/**
* Create a new ZipEntryHandler.
*
@@ -58,31 +64,40 @@
{
super(context, parent, name);
- url = context.getChildURL(parent, name);
+ this.isLeaf = isLeaf;
+ if(parent != null)
+ {
+ context.addChild(parent, this);
+ }
+ }
- String currentUrl = url.toString();
- int pos = currentUrl.indexOf(":/");
+ private synchronized void init()
+ {
+ if (initialized)
+ return;
+
StringBuilder vfsUrl = new StringBuilder();
- vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
try
{
+ url = getZipEntryContext().getChildURL(getParent(), getName());
+ String currentUrl = url.toString();
+ int pos = currentUrl.indexOf(":/");
+ vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
+
if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
vfsUrl.append("/");
setVfsUrl(new URL(vfsUrl.toString()));
}
- catch(MalformedURLException ex)
+ catch(Exception ex)
{
throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
}
-
- if(parent != null)
- {
- context.addChild(parent, this);
- }
+ initialized = true;
}
public URI toURI() throws URISyntaxException
{
+ init();
return VFSUtils.toURI(url);
}
@@ -171,4 +186,10 @@
{
return ((ZipEntryContext) getLocalVFSContext());
}
+
+ public URL toVfsUrl()
+ {
+ init();
+ return super.getVfsUrl();
+ }
}
Modified: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java 2008-08-12 18:29:31 UTC (rev 76995)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java 2008-08-12 20:51:05 UTC (rev 76996)
@@ -21,6 +21,7 @@
*/
package org.jboss.test.virtual.test;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
@@ -29,6 +30,7 @@
import junit.framework.Test;
import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
import org.jboss.virtual.plugins.context.file.FileSystemContext;
import org.jboss.virtual.plugins.context.jar.JarUtils;
import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
@@ -79,16 +81,8 @@
InputStream is = url.openStream();
OutputStream os = new FileOutputStream(tmpJar);
+ VFSUtils.copyStreamAndClose(is, os);
- byte [] buff = new byte[65536];
- int count = is.read(buff);
- while(count != -1)
- {
- os.write(buff, 0, count);
- count = is.read(buff);
- }
- os.close();
-
ZipEntryContext context = new ZipEntryContext(tmpJar.toURL());
assertTrue("context.getRoot().exists()", context.getRoot().exists());
@@ -109,13 +103,52 @@
URL url = getResource("/vfs/context/jar/");
FileSystemContext ctx = new FileSystemContext(url);
- // check that vfszip is active
+ // we just do basic sanity checks
+
+ // valid archive
+
VirtualFileHandler handler = ctx.getRoot().getChild("archive.jar");
- assertTrue("is vfszip", "vfszip".equals(handler.toURL().getProtocol()));
+ //assertTrue("is vfszip", "vfszip".equals(handler.toURL().getProtocol()));
assertFalse("is leaf", handler.isLeaf());
+ assertTrue("exists", handler.exists());
+ assertNotNull("pathName not null", handler.getPathName());
+ assertNotNull("name not null", handler.getName());
+ assertNotNull("parent not null", handler.getParent());
+ assertTrue("lastModified > 0", handler.getLastModified() > 0);
+ assertTrue("size > 0", handler.getSize() > 0);
+ assertNotNull("VF not null", handler.getVirtualFile());
+ assertFalse("hasBeenModified == false", handler.hasBeenModified());
+ assertFalse("hidden == false", handler.isHidden());
+ assertFalse("nested == false", handler.isNested());
+ assertNotNull("toURI not null", handler.toURI());
+ assertNotNull("toURL not null", handler.toURL());
+ assertNotNull("toVfsUrl not null", handler.toVfsUrl());
+ ByteArrayOutputStream memOut = new ByteArrayOutputStream();
+ VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
+ assertTrue("read archive content", memOut.size() == handler.getSize());
+
+ // invalid archive
+
handler = ctx.getRoot().getChild("notanarchive.jar");
- assertTrue("is leaf", handler.isLeaf());
+ //assertTrue("is leaf", handler.isLeaf());
+ assertTrue("exists", handler.exists());
+ assertTrue("lastModified > 0", handler.getLastModified() > 0);
+ assertNotNull("pathName not null", handler.getPathName());
+ assertNotNull("name not null", handler.getName());
+ assertNotNull("parent not null", handler.getParent());
+ assertTrue("size > 0", handler.getSize() > 0);
+ assertNotNull("VF not null", handler.getVirtualFile());
+ assertFalse("hasBeenModified == false", handler.hasBeenModified());
+ assertFalse("hidden == false", handler.isHidden());
+ assertFalse("nested == false", handler.isNested());
+ assertNotNull("toURI not null", handler.toURI());
+ assertNotNull("toURL not null", handler.toURL());
+ assertNotNull("toVfsUrl not null", handler.toVfsUrl());
+
+ memOut = new ByteArrayOutputStream();
+ VFSUtils.copyStreamAndClose(handler.openStream(), memOut);
+ assertTrue("read archive content", memOut.size() == handler.getSize());
}
// we need to make sure this doesn't get touched before
More information about the jboss-cvs-commits
mailing list