[jboss-cvs] JBossAS SVN: r73901 - in projects/vfs/trunk/src: main/java/org/jboss/virtual/plugins/context and 6 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sun Jun 1 14:25:04 EDT 2008
Author: mstruk
Date: 2008-06-01 14:25:02 -0400 (Sun, 01 Jun 2008)
New Revision: 73901
Added:
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/SizeLimitedInputStream.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/ZipEntryContextFactory.java
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/ZipEntryInputStream.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipStreamWrapper.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipWrapper.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/
projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java
Removed:
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/ZipEntryContextFactory.java
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/ZipEntryInputStream.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java
Modified:
projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java
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/DelegatingHandler.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContext.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContextFactoryLocator.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java
Log:
JBVFS-27 Merged-in jar-alter-work branch (72871:72996, 72997:73688, 73689:73900)
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -46,9 +46,11 @@
import org.jboss.logging.Logger;
import org.jboss.util.StringPropertyReplacer;
import org.jboss.util.id.GUID;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
import org.jboss.virtual.plugins.context.file.FileSystemContext;
import org.jboss.virtual.plugins.context.jar.AbstractJarHandler;
import org.jboss.virtual.plugins.context.jar.NestedJarHandler;
+import org.jboss.virtual.plugins.context.zip.ZipEntryHandler;
import org.jboss.virtual.spi.LinkInfo;
import org.jboss.virtual.spi.VFSContext;
import org.jboss.virtual.spi.VirtualFileHandler;
@@ -76,6 +78,17 @@
public static final String FORCE_COPY_KEY = "jboss.vfs.forceCopy";
public static final String USE_COPY_QUERY = "useCopyJarHandler";
+ /**
+ * Key used to force fallback from vfszip (default) to vfsjar
+ */
+ public static final String FORCE_VFS_JAR_KEY = "jboss.vfs.forceVfsJar";
+
+ /**
+ * Key used to turn off reaper mode in vfszip - forcing synchronous (slower) handling of files
+ */
+ public static final String FORCE_NO_REAPER_KEY = "jboss.vfs.forceNoReaper";
+ public static final String NO_REAPER_QUERY = "noReaper";
+
private static File tempDir;
private static class GetTempDir implements PrivilegedAction<File>
@@ -87,7 +100,7 @@
}
}
- private synchronized static File getTempDirectory()
+ public synchronized static File getTempDirectory()
{
if (tempDir == null)
{
@@ -494,7 +507,12 @@
VirtualFileHandler handler = file.getHandler();
// already unpacked
- if (handler instanceof NestedJarHandler || handler instanceof AbstractJarHandler == false)
+ VirtualFileHandler unwrapped = handler;
+ if (unwrapped instanceof DelegatingHandler)
+ unwrapped = ((DelegatingHandler) unwrapped).getDelegate();
+
+ if (unwrapped instanceof ZipEntryHandler == false
+ && (unwrapped instanceof NestedJarHandler || unwrapped instanceof AbstractJarHandler == false))
{
if (log.isTraceEnabled())
log.trace("Should already be unpacked: " + file);
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-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -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,35 @@
return parent.getChild(path);
}
+ public URL getChildURL(VirtualFileHandler parent, String name) throws IOException
+ {
+ StringBuilder urlStr = new StringBuilder(256);
+ URI rootUri = getRootURI();
+ urlStr.append(rootUri.getScheme())
+ .append(":").append(rootUri.getPath());
+ if(parent != null)
+ {
+ String pPathName = null;
+ if(parent instanceof AbstractVirtualFileHandler)
+ pPathName = ((AbstractVirtualFileHandler)parent).getLocalPathName();
+ else
+ pPathName = parent.getPathName();
+
+ if (urlStr.charAt( urlStr.length()-1) != '/')
+ urlStr.append("/");
+
+ if(pPathName.length() != 0)
+ urlStr.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 +246,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/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-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -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/trunk/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/DelegatingHandler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -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,36 @@
{
delegate.replaceChild(original, replacement);
}
+
+ public URL toVfsUrl() throws MalformedURLException, URISyntaxException
+ {
+ return delegate.toVfsUrl();
+ }
+
+ public int hashCode()
+ {
+ if (delegate != null)
+ return delegate.hashCode();
+
+ return super.hashCode();
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == this)
+ return true;
+
+ if (o instanceof DelegatingHandler)
+ {
+ DelegatingHandler handler = (DelegatingHandler) o;
+ if (delegate != null)
+ return delegate.equals(handler.delegate);
+ else if (handler.delegate != null)
+ return false; // one is null
+ else
+ return true; // both are null
+ }
+
+ return false;
+ }
}
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -27,26 +27,51 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.List;
import java.util.Properties;
import org.jboss.virtual.VFSUtils;
import org.jboss.virtual.VirtualFile;
import org.jboss.virtual.plugins.context.AbstractVFSContext;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
import org.jboss.virtual.plugins.context.jar.JarHandler;
import org.jboss.virtual.plugins.context.jar.JarUtils;
import org.jboss.virtual.spi.LinkInfo;
import org.jboss.virtual.spi.VirtualFileHandler;
+import org.jboss.logging.Logger;
/**
* FileSystemContext.
+ *
+ * Jar archives are processed through {@link org.jboss.virtual.plugins.context.zip.ZipEntryContext}.
+ *
+ * To switch back to {@link org.jboss.virtual.plugins.context.jar.JarHandler}
+ * set a system property <em>jboss.vfs.forceVfsJar=true</em>
*
* @author <a href="adrian at jboss.com">Adrian Brock</a>
* @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
* @version $Revision: 1.1 $
*/
public class FileSystemContext extends AbstractVFSContext
{
+
+ private static final Logger log = Logger.getLogger(ZipEntryContext.class);
+
+ /** true if forcing fallback to vfsjar from default vfszip */
+ private static boolean forceVfsJar;
+
+ static
+ {
+ forceVfsJar = AccessController.doPrivileged(new CheckForceVfsJar());
+
+ if (forceVfsJar)
+ log.warn("VFS forced fallback to vfsjar is enabled.");
+ }
+
/** The root file */
private final VirtualFileHandler root;
@@ -188,18 +213,45 @@
String name = file.getName();
if (file.isFile() && JarUtils.isArchive(name))
{
- try
+ if (forceVfsJar)
{
return new JarHandler(this, parent, file, file.toURL(), name);
}
- catch (IOException e)
+ else
{
- log.debug("Exception while trying to handle file (" + name + ") as a jar: " + e.getMessage());
+ try
+ {
+ DelegatingHandler delegator = mountZipFS(parent, name, file);
+ return delegator;
+ }
+ catch (Exception e)
+ {
+ IOException ex = new IOException("Exception while trying to handle file (" + name + ") through ZipEntryContext: ");
+ ex.initCause(e);
+ throw ex;
+ }
}
}
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
*
@@ -274,4 +326,14 @@
rootFile.close();
super.finalize();
}
+
+ private static class CheckForceVfsJar implements PrivilegedAction<Boolean>
+ {
+ public Boolean run()
+ {
+ String forceString = System.getProperty(VFSUtils.FORCE_VFS_JAR_KEY, "false");
+ return Boolean.valueOf(forceString);
+ }
+ }
+
}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip)
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/SizeLimitedInputStream.java (from rev 73900, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/SizeLimitedInputStream.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/SizeLimitedInputStream.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/SizeLimitedInputStream.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,86 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+/**
+ * SizeLimitedInputStream
+ *
+ * Signals EOF when the specified number of bytes
+ * have been read from the underlying stream
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class SizeLimitedInputStream extends InputStream
+{
+
+ private InputStream in;
+
+ private int togo;
+
+ public SizeLimitedInputStream(InputStream ins, int size)
+ {
+ this.in = ins;
+ this.togo = size;
+ }
+
+ public int read() throws IOException
+ {
+ int b = -1;
+ if (togo > 0)
+ {
+ b = in.read();
+ if (b != -1)
+ togo--;
+ }
+ return b;
+ }
+
+ public int read(byte [] buf) throws IOException
+ {
+ return read(buf, 0, buf.length);
+ }
+
+ public int read(byte [] buf, int offs, int len) throws IOException
+ {
+ int rc = -1;
+
+ if (togo > 0)
+ {
+ rc = togo < len ? togo : len;
+ rc = in.read(buf, offs, rc);
+ if (rc != -1)
+ togo -= rc;
+ }
+
+ return rc;
+ }
+
+ public void close() throws IOException
+ {
+ in.close();
+ }
+}
\ No newline at end of file
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,639 +0,0 @@
-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
- }
-
- }
-
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java (from rev 72878, projects/vfs/branches/jar-alter-work/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 (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,929 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractVFSContext;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.plugins.context.DelegatingHandler;
+import org.jboss.virtual.plugins.context.jar.JarUtils;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipEntry;
+
+/**
+ * <tt>ZipEntryContext</tt> implements a {@link org.jboss.virtual.spi.VFSContext}
+ * that exposes a zip archive as a virtual file system.
+ *
+ * Zip archive can be in a form of a file or a stream.
+ *
+ * Nested archives are processed through this same class.
+ * By default nested archives are cached in memory and mounted as new
+ * instances of <tt>ZipEntryContext</tt> with <tt>ZipStremWrapper</tt> as a source.
+ * If system property <em>jboss.vfs.forceCopy=true</em> is specified,
+ * or URL query parameter <em>forceCopy=true</em> is present,
+ * nested archives are extracted into a temp directory before being
+ * mounted as new instances of <tt>ZipEntryContext</tt>.
+ *
+ * This context implementation has two modes of releasing file locks.
+ * <em>Asynchronous</em> mode is the default one since it is better performant.
+ * To switch this to <em>synchronous</em> mode a system property
+ * <em>jboss.vfs.forceNoReaper=true</em> can be specified or URL query parameter
+ * <em>noReaper=true</em> can be included in context URL.
+ *
+ * This context implementation is a replacement for
+ * {@link org.jboss.virtual.plugins.context.jar.JarContext}.
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipEntryContext extends AbstractVFSContext
+{
+
+ private static final Logger log = Logger.getLogger(ZipEntryContext.class);
+
+ /** Global setting for nested archive processing mode: copy or no-copy (default) */
+ private static boolean forceCopy;
+
+ static
+ {
+ deleteTmpDirContents();
+
+ forceCopy = AccessController.doPrivileged(new CheckForceCopy());
+
+ if (forceCopy)
+ log.info("VFS force nested jars copy-mode is enabled.");
+ }
+
+
+ /** Abstracted access to zip archive - either ZipFileWrapper or ZipStreamWrapper */
+ private ZipWrapper zipSource;
+
+ /** Entry path representing a context root - archive root is not necessarily a context root */
+ private String rootEntryPath = "";
+
+ /** AutoClean signals if zip archive should be deleted after closing the context - true for nested archives */
+ private boolean autoClean = false;
+
+ /** Registry of everything that zipSource contains */
+ private ConcurrentHashMap<String, EntryInfo> entries = new ConcurrentHashMap<String, EntryInfo>();
+
+
+ /**
+ * Create a new ZipEntryContext
+ *
+ * @param rootURL - file or jar:file url
+ * @throws URISyntaxException
+ * @throws IOException
+ */
+ public ZipEntryContext(URL rootURL) throws URISyntaxException, IOException
+ {
+ this(rootURL, false);
+ }
+
+ /**
+ * Create a new ZipEntryContext
+ *
+ * @param rootURL - file or jar:file url
+ * @param autoClean - true if file represented by rootURL should be deleted after this context is closed
+ * @throws URISyntaxException
+ * @throws java.io.IOException
+ */
+ public ZipEntryContext(URL rootURL, boolean autoClean) throws URISyntaxException, IOException
+ {
+ super(VFSUtils.toURI(fixUrl(rootURL)));
+ this.autoClean = autoClean;
+ init(rootURL, null, null);
+ }
+
+ /**
+ * Create a new ZipEntryContext to be mounted into another context
+ *
+ * @param rootURL - url representing this context within another context
+ * @param peer - file handler in another context through which this context is being mounted
+ * @param localRootUrl - file or jar:file url
+ * @throws URISyntaxException
+ * @throws java.io.IOException
+ */
+ public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl) throws URISyntaxException, IOException
+ {
+ this(rootURL, peer, localRootUrl, false);
+ }
+
+ /**
+ * Create a new ZipEntryContext to be mounted into another context
+ *
+ * @param rootURL - url representing this context within another context
+ * @param peer - file handler in another context through which this context is being mounted
+ * @param localRootUrl - file or jar:file url
+ * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
+ * @throws URISyntaxException
+ * @throws IOException
+ */
+ public ZipEntryContext(URL rootURL, VirtualFileHandler peer, URL localRootUrl, boolean autoClean) throws URISyntaxException, IOException
+ {
+ super(VFSUtils.toURI(fixUrl(rootURL)));
+ this.autoClean = autoClean;
+ init(localRootUrl, peer, null);
+ }
+
+ /**
+ * Create a new ZipEntryContext to be mounted into another context
+ *
+ * @param rootURL - url representing this context within another context
+ * @param peer - file handler in another context through which this context is being mounted
+ * @param zipWrapper - abstracted zip archive source
+ * @param autoClean - true if file represented by localRootURL should be deleted after this context is closed
+ * @throws URISyntaxException
+ * @throws IOException
+ */
+ public ZipEntryContext(URL rootURL, VirtualFileHandler peer, ZipWrapper zipWrapper, boolean autoClean) throws URISyntaxException, IOException
+ {
+ super(VFSUtils.toURI(fixUrl(rootURL)));
+ this.autoClean = autoClean;
+ init(null, peer, zipWrapper);
+ }
+
+ /**
+ * Extra initialization that couldn't fit inside constructors
+ *
+ * @param localRootURL
+ * @param peer
+ * @param zipWrapper
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ private void init(URL localRootURL, VirtualFileHandler peer, ZipWrapper zipWrapper) throws IOException, URISyntaxException
+ {
+
+ if (zipWrapper == null)
+ {
+ if (localRootURL == null)
+ throw new IllegalArgumentException("No ZipWrapper specified and localRootURL is null");
+
+ // initialize rootEntryPath and get archive file path
+ String rootPath = initRootAndPath(localRootURL);
+
+ String noReaper = getOptions().get(VFSUtils.NO_REAPER_QUERY);
+ zipSource = new ZipFileWrapper(VFSUtils.toURI(new URL(rootPath)), autoClean, Boolean.valueOf(noReaper));
+ }
+ else
+ {
+ zipSource = zipWrapper;
+ }
+
+ setRootPeer(peer);
+
+ String name = getRootURI().toString();
+ int toPos = name.length();
+
+ // cut off any ending slash
+ if(name.length() != 0 && name.charAt(name.length()-1) == '/')
+ toPos --;
+
+ // name is last path component
+ int namePos = name.lastIndexOf("/", toPos-1);
+ name = name.substring(namePos+1, toPos);
+
+ // cut off any ending exclamation
+ if(name.length() != 0 && name.charAt(name.length()-1) == '!')
+ name = name.substring(0, name.length()-1);
+
+ // init initial root EntryInfo that will be overwritten
+ // if zip entry exists for rootEntryPath
+ entries.put("", new EntryInfo(new ZipEntryHandler(this, null, name, true), null));
+
+ initEntries();
+ ZipEntryContextFactory.registerContext(this);
+ }
+
+ /**
+ * Returns archive file name - if this is a top-level ZipEntryContext.
+ * Otherwise it returns the last component of URL.
+ *
+ * @return name
+ */
+ public String getName()
+ {
+ VirtualFileHandler peer = getRootPeer();
+ if (peer != null)
+ return peer.getName();
+ else
+ return zipSource.getName();
+ }
+
+ /**
+ * Iterate through zip archive entries, compose a tree structure of archive's content
+ *
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ private synchronized void initEntries() throws IOException, URISyntaxException
+ {
+
+ // we're using a two phase approach - we first select the relevant ones
+ // then we order these by name and only then we process them
+ // this way we ensure that parent entries are processed before child entries
+
+ HashMap<String, ZipEntry> relevant = new HashMap<String, ZipEntry>();
+ zipSource.acquire();
+ try
+ {
+ Enumeration<? extends ZipEntry> zipEntries = zipSource.entries();
+
+ // zoom-in on entries under rootEntryPath - ignoring the rest
+ while(zipEntries.hasMoreElements())
+ {
+ ZipEntry ent = zipEntries.nextElement();
+ if(ent.getName().startsWith(rootEntryPath))
+ {
+ relevant.put(ent.getName(), ent);
+ }
+ }
+
+ TreeMap<String, ZipEntry> orderedRelevant = new TreeMap<String, ZipEntry>(relevant);
+
+ for(Map.Entry<String, ZipEntry> entry : orderedRelevant.entrySet())
+ {
+ ZipEntry ent = entry.getValue();
+ String fullName = ent.getName().substring(rootEntryPath.length());
+
+ String [] split = splitParentChild(fullName);
+ String parentPath = split[0];
+ String name = split[1];
+
+ EntryInfo ei = entries.get(parentPath);
+ if(ei == null)
+ ei = makeDummyParent(parentPath);
+
+ AbstractVirtualFileHandler parent = ei != null ? ei.handler : null;
+
+ if(ent.isDirectory() == false && JarUtils.isArchive(ent.getName()))
+ {
+ boolean useCopyMode = forceCopy;
+ if (useCopyMode == false)
+ {
+ String flag = getOptions().get(VFSUtils.USE_COPY_QUERY);
+ useCopyMode = Boolean.valueOf(flag);
+ }
+
+ DelegatingHandler delegator;
+
+ if (useCopyMode)
+ {
+ // extract it to temp dir
+ File dest = new File(getTempDir() + "/" + getTempFileName(ent.getName()));
+ dest.deleteOnExit();
+
+ // ensure parent exists
+ dest.getParentFile().mkdirs();
+
+ InputStream is = zipSource.openStream(ent);
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(dest));
+ copyStreamAndClose(is, os);
+
+ // mount another instance of ZipEntryContext
+ delegator = mountZipFile(parent, name, dest);
+ }
+ else
+ {
+ // mount another instance of ZipEntryContext
+ delegator = mountZipStream(parent, name, zipSource.openStream(ent));
+ }
+
+ entries.put(delegator.getLocalPathName(), new EntryInfo(delegator, ent));
+ addChild(parent, delegator);
+ }
+ else
+ {
+ ZipEntryHandler wrapper = new ZipEntryHandler(this, parent, name, ent.isDirectory() == false);
+ entries.put(wrapper.getLocalPathName(), new EntryInfo(wrapper, ent));
+ }
+
+ }
+ }
+ finally
+ {
+ zipSource.release();
+ }
+
+ }
+
+ /**
+ * Mount ZipEntryContext created around extracted nested archive
+ *
+ * @param parent
+ * @param name
+ * @param file
+ * @return
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ protected DelegatingHandler mountZipFile(VirtualFileHandler parent, String name, File file) throws IOException, URISyntaxException
+ {
+ DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+ URL fileUrl = file.toURL();
+ URL delegatorUrl = fileUrl;
+
+ if (parent != null)
+ delegatorUrl = getChildURL(parent, name);
+
+ ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, fileUrl, true);
+ VirtualFileHandler handler = ctx.getRoot();
+ delegator.setDelegate(handler);
+
+ return delegator;
+ }
+
+ /**
+ * Mount ZipEntryContext created around ZipStreamWrapper
+ *
+ * @param parent
+ * @param name
+ * @param zipStream
+ * @return
+ * @throws IOException
+ * @throws URISyntaxException
+ */
+ protected DelegatingHandler mountZipStream(VirtualFileHandler parent, String name, InputStream zipStream) throws IOException, URISyntaxException
+ {
+ DelegatingHandler delegator = new DelegatingHandler(this, parent, name);
+ ZipStreamWrapper wrapper = new ZipStreamWrapper(zipStream, name, parent.getLastModified());
+
+ URL delegatorUrl = null;
+
+ if (parent != null)
+ delegatorUrl = getChildURL(parent, name);
+
+ ZipEntryContext ctx = new ZipEntryContext(delegatorUrl, delegator, wrapper, false);
+ VirtualFileHandler handler = ctx.getRoot();
+ delegator.setDelegate(handler);
+
+ return delegator;
+ }
+
+ /**
+ * Zip archives sometimes don't contain directory entries - only leaf entries
+ *
+ * @param parentPath
+ * @return
+ * @throws IOException
+ */
+ private EntryInfo makeDummyParent(String parentPath) throws IOException
+ {
+ // get grand parent first
+ String [] split = splitParentChild(parentPath);
+ String grandPa = split[0];
+
+ EntryInfo eiParent = entries.get(grandPa);
+ if(eiParent == null)
+ eiParent = makeDummyParent(grandPa);
+
+ ZipEntryHandler handler = new ZipEntryHandler(this, eiParent.handler, split[1], false);
+ EntryInfo ei = new EntryInfo(handler, null);
+ entries.put(parentPath, ei);
+ return ei;
+ }
+
+ /**
+ * Initialize rootEntryPath and return archive file path
+ *
+ * @param localRootUrl
+ * @return
+ */
+ private String initRootAndPath(URL localRootUrl)
+ {
+ String filePath = localRootUrl.toString();
+ String zipPath = filePath;
+
+ int pos = filePath.indexOf("!");
+ if(pos > 0)
+ {
+ zipPath = filePath.substring(0, pos);
+ rootEntryPath = filePath.substring(pos+2);
+ if(rootEntryPath.length() != 0)
+ rootEntryPath += "/";
+ }
+
+ // find where url protocol ends - i.e. jar:file:/ ...
+ pos= zipPath.indexOf(":/");
+ filePath = zipPath.substring(pos+1);
+
+ // cut out url query part if present
+ int queryStart = filePath.indexOf("?");
+ if (queryStart != -1)
+ filePath = filePath.substring(0, queryStart);
+
+ return "file:" + filePath;
+ }
+
+ /**
+ * If archive has been modified, clear <em>entries</em> and re-initialize
+ */
+ private synchronized void checkIfModified()
+ {
+ // TODO: if zipSource represents a nested archive we should maybe delegate lastModified to its parent
+ if (zipSource.hasBeenModified())
+ {
+ EntryInfo rootInfo = entries.get("");
+ entries = new ConcurrentHashMap<String, EntryInfo>();
+ entries.put("", rootInfo);
+
+ if (zipSource.exists())
+ {
+ try
+ {
+ initEntries();
+ }
+ catch(Exception ignored)
+ {
+ log.warn("IGNORING: Failed to reinitialize context: " + getRootURI(), ignored);
+ }
+ }
+ }
+ }
+
+ public VirtualFileHandler getRoot() throws IOException
+ {
+ return entries.get("").handler;
+ }
+
+ public VirtualFileHandler getChild(ZipEntryHandler parent, String name)
+ {
+ if (parent == null)
+ throw new IllegalArgumentException("Null parent");
+
+ checkIfModified();
+ String pathName = parent.getLocalPathName();
+ if("".equals(pathName))
+ pathName = name;
+ else
+ pathName = pathName + "/" + name;
+
+ EntryInfo ei = entries.get(pathName);
+
+ if(ei != null)
+ return ei.handler;
+
+ return null;
+ }
+
+ public List<VirtualFileHandler> getChildren(VirtualFileHandler parent, boolean ignoreErrors) throws IOException
+ {
+ if (parent == null)
+ throw new IllegalArgumentException("Null parent");
+
+ checkIfModified();
+ if(parent instanceof AbstractVirtualFileHandler)
+ {
+ AbstractVirtualFileHandler parentHandler = (AbstractVirtualFileHandler) parent;
+ EntryInfo parentEntry = entries.get(parentHandler.getLocalPathName());
+ if (parentEntry != null)
+ {
+ if (parentEntry.handler instanceof DelegatingHandler)
+ return parentEntry.handler.getChildren(ignoreErrors);
+
+ return parentEntry.getChildren();
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ public long getLastModified(ZipEntryHandler handler)
+ {
+ if (handler == null)
+ throw new IllegalArgumentException("Null handler");
+
+ checkIfModified();
+ EntryInfo ei = entries.get(handler.getLocalPathName());
+ if(ei == null)
+ return 0;
+
+ if(ei.entry == null) {
+ return zipSource.getLastModified();
+ }
+
+ return ei.entry.getTime();
+ }
+
+ public long getSize(ZipEntryHandler handler)
+ {
+ if (handler == null)
+ throw new IllegalArgumentException("Null handler");
+
+ checkIfModified();
+ String pathName = handler.getLocalPathName();
+ EntryInfo ei = entries.get(pathName);
+ if(ei == null)
+ return 0;
+
+ if(ei.entry == null)
+ {
+ if(pathName.length() == 0)
+ return zipSource.getSize();
+ else
+ return 0;
+ }
+
+ return ei.entry.getSize();
+ }
+
+ public boolean exists(ZipEntryHandler handler)
+ {
+ if (handler == null)
+ throw new IllegalArgumentException("Null handler");
+
+ checkIfModified();
+ String pathName = handler.getLocalPathName();
+ EntryInfo ei = entries.get(pathName);
+ if(ei == null)
+ return false;
+
+ if (ei.entry == null && pathName.length() == 0)
+ return zipSource.exists();
+
+ return true;
+ }
+
+ public boolean isLeaf(ZipEntryHandler handler)
+ {
+ if (handler == null)
+ throw new IllegalArgumentException("Null handler");
+
+ checkIfModified();
+ EntryInfo ei = entries.get(handler.getLocalPathName());
+ if(ei == null || ei.entry == null)
+ return false;
+
+ return !ei.entry.isDirectory();
+ }
+
+ public InputStream openStream(ZipEntryHandler handler) throws IOException
+ {
+ if (handler == null)
+ throw new IllegalArgumentException("Null handler");
+
+ checkIfModified();
+ 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, ex);
+ }
+ throw new FileNotFoundException(uriStr);
+
+ }
+
+ if(ei.entry == null)
+ {
+ return zipSource.getRootAsStream();
+ }
+
+ return zipSource.openStream(ei.entry);
+ }
+
+ public void addChild(AbstractVirtualFileHandler parent, AbstractVirtualFileHandler child)
+ {
+ if (parent == null)
+ throw new IllegalArgumentException("Null parent");
+
+ if (child == null)
+ throw new IllegalArgumentException("Null child");
+
+ EntryInfo parentEntry = entries.get(parent.getLocalPathName());
+ if (parentEntry != null)
+ parentEntry.add(child);
+ else
+ throw new RuntimeException("Parent does not exist: " + parent);
+ }
+
+
+
+ protected void finalize()
+ {
+ try
+ {
+ super.finalize();
+ zipSource.close();
+ }
+ catch (Throwable ignored)
+ {
+ log.debug("IGNORING: Failed to close zip source: " + zipSource, ignored);
+ }
+ }
+
+
+ public void replaceChild(ZipEntryHandler parent, AbstractVirtualFileHandler original, VirtualFileHandler replacement)
+ {
+ EntryInfo parentEntry = entries.get(parent.getLocalPathName());
+ if (parentEntry != null)
+ {
+ DelegatingHandler newOne;
+
+ if (replacement instanceof DelegatingHandler)
+ {
+ newOne = (DelegatingHandler) replacement;
+ }
+ else
+ {
+ DelegatingHandler delegator = new DelegatingHandler(this, parent, original.getName(), replacement);
+ newOne = delegator;
+ }
+
+ synchronized(this)
+ {
+ parentEntry.replaceChild(original, newOne);
+
+ EntryInfo ei = entries.get(original.getLocalPathName());
+ ei.handler = newOne;
+ ei.entry = null;
+ ei.clearChildren();
+ }
+ }
+ else
+ {
+ throw new RuntimeException("Parent does not exist: " + parent);
+ }
+ }
+
+
+ /**
+ * Internal data structure holding meta information of a virtual file in this context
+ */
+ static class EntryInfo
+ {
+ private AbstractVirtualFileHandler handler;
+ private ZipEntry entry;
+ private List<AbstractVirtualFileHandler> children;
+
+ EntryInfo(AbstractVirtualFileHandler handler, ZipEntry entry)
+ {
+ this.handler = handler;
+ this.entry = entry;
+ }
+
+ public synchronized List<VirtualFileHandler> getChildren()
+ {
+ if (children == null)
+ return Collections.emptyList();
+
+ return new LinkedList<VirtualFileHandler>(children);
+ }
+
+ public synchronized void replaceChild(AbstractVirtualFileHandler original, AbstractVirtualFileHandler replacement)
+ {
+ if (children != null)
+ {
+ int i = 0;
+ Iterator<AbstractVirtualFileHandler> it = children.iterator();
+ while(it.hasNext())
+ {
+ AbstractVirtualFileHandler child = it.next();
+ if (child.getName().equals(original.getName()))
+ {
+ children.set(i, replacement);
+ break;
+ }
+ i++;
+ }
+ }
+ }
+
+ public synchronized void clearChildren()
+ {
+ if (children != null)
+ children.clear();
+ }
+
+ public synchronized void add(AbstractVirtualFileHandler child)
+ {
+ if (children == null)
+ {
+ children = new LinkedList<AbstractVirtualFileHandler>();
+ }
+ else
+ {
+ // if a child exists with this name already, remove it
+ Iterator<AbstractVirtualFileHandler> it = children.iterator();
+ while (it.hasNext())
+ {
+ AbstractVirtualFileHandler handler = it.next();
+ if (handler.getName().equals(child.getName()))
+ {
+ it.remove();
+ break;
+ }
+ }
+ }
+
+ children.add(child);
+ }
+ }
+
+
+
+ //
+ // Helper methods
+ //
+
+
+
+ /**
+ * Copy input stream to output stream and close them both
+ *
+ * @param is
+ * @param os
+ * @throws IOException
+ */
+ static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException
+ {
+ try
+ {
+ byte [] buff = new byte[65536];
+ int count = is.read(buff);
+ while(count != -1)
+ {
+ os.write(buff, 0, count);
+ count = is.read(buff);
+ }
+ }
+ finally
+ {
+ if(is != null)
+ {
+ try {
+ is.close();
+ }
+ catch(Exception ignored)
+ {
+ }
+ }
+ os.close();
+ }
+ }
+
+ /**
+ * Make sure url protocol is <em>vfszip</em>
+ *
+ * @param rootURL
+ * @return
+ * @throws MalformedURLException
+ */
+ private static URL fixUrl(URL rootURL) throws MalformedURLException
+ {
+ if ("vfszip".equals(rootURL.getProtocol()) == false)
+ {
+ String url = rootURL.toString();
+ int pos = url.indexOf(":/");
+ if (pos != -1)
+ url = url.substring(pos);
+
+ return new URL("vfszip" + url);
+ }
+ return rootURL;
+ }
+
+ /**
+ * Break to path + name
+ *
+ * @param pathName
+ * @return
+ */
+ public static String [] splitParentChild(String pathName)
+ {
+ if(pathName.length() == 0)
+ return new String [] {null, pathName};
+
+ int toPos = pathName.length();
+ if(pathName.charAt(pathName.length()-1) == '/')
+ toPos --;
+
+ int delimPos = pathName.lastIndexOf('/', toPos-1);
+
+ String [] ret;
+ if(delimPos == -1)
+ {
+ ret = new String []
+ {
+ "",
+ pathName.substring(delimPos+1, toPos)
+ };
+ }
+ else
+ {
+ ret = new String []
+ {
+ pathName.substring(0, delimPos),
+ pathName.substring(delimPos+1, toPos)
+ };
+ }
+ return ret;
+ }
+
+
+ /**
+ * Temporary files naming scheme
+ *
+ * @param name
+ * @return
+ */
+ private static String getTempFileName(String name)
+ {
+ int delim = name.lastIndexOf("/");
+ if (delim != -1)
+ name = name.substring(delim+1);
+ return UUID.randomUUID().toString().substring(0, 8) + "_" + name;
+ }
+
+ /**
+ * Use VFS's temp directory and make 'vfs-nested' sub-directory inside it for our purposes
+ *
+ * @return
+ */
+ private static String getTempDir()
+ {
+ File dir = new File(VFSUtils.getTempDirectory(), "vfs-nested.tmp");
+ return dir.toString();
+ }
+
+ /**
+ * Delete first-level files only, don't drill down
+ */
+ private static void deleteTmpDirContents()
+ {
+ try
+ {
+ File tmpDir = new File(getTempDir());
+ File [] files = tmpDir.listFiles();
+ for (File file: files)
+ {
+ if (!file.isDirectory() && !file.isHidden())
+ file.delete();
+ }
+ }
+ catch(Exception ignored)
+ {
+ }
+
+ }
+
+
+ private static class CheckForceCopy implements PrivilegedAction<Boolean>
+ {
+ public Boolean run()
+ {
+ String forceString = System.getProperty(VFSUtils.FORCE_COPY_KEY, "false");
+ return Boolean.valueOf(forceString);
+ }
+ }
+}
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,97 +0,0 @@
-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);
- }
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContextFactory.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,129 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.virtual.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
+{
+ /** registry of all ZipEntryContext instances */
+ private static Map<String, ZipEntryContext> ctxCache = new ConcurrentHashMap<String, ZipEntryContext>();
+
+ /** singleton */
+ private static ZipEntryContextFactory instance = new ZipEntryContextFactory();
+
+ /**
+ * ZipEntryContextFactory registers two url protocols: <em>zip</em> and <em>vfszip</em>
+ */
+ public ZipEntryContextFactory()
+ {
+ super("zip", "vfszip"); // "jar", "vfsjar",
+ }
+
+ public VFSContext getVFS(URI rootURI) throws IOException
+ {
+ return getVFS(rootURI.toURL());
+ }
+
+ /**
+ * Find a best matching existing ZipEntryContext, or create a new one if none matches.
+ *
+ * @param rootURL
+ * @return
+ * @throws IOException
+ */
+ 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;
+ }
+
+ // ZipEntryContext registers newly created context with this factory
+ // by calling registerContext() which puts a newly created context into ctxCache
+
+ 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);
+ }
+}
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,122 +0,0 @@
-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());
- }
-
-
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java (from rev 72878, projects/vfs/branches/jar-alter-work/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 (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryHandler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,158 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.plugins.context.AbstractVirtualFileHandler;
+import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
+import org.jboss.virtual.spi.VirtualFileHandler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Handler representing an individual file (ZipEntry) within ZipEntryContext
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipEntryHandler extends AbstractVirtualFileHandler implements StructuredVirtualFileHandler
+{
+
+ /** The url */
+ private final URL url;
+
+
+ /**
+ * Create a new ZipEntryHandler.
+ *
+ * @param context ZipEntryContext
+ * @param parent parent within the same context
+ * @param name name of this file within context
+ * @param isLeaf true if this file should have a URL not ending with '/', false otherwise
+ */
+ public ZipEntryHandler(ZipEntryContext context, AbstractVirtualFileHandler parent, String name, boolean isLeaf) throws IOException
+ {
+ super(context, parent, name);
+
+ url = context.getChildURL(parent, name);
+
+ String currentUrl = url.toString();
+ int pos = currentUrl.indexOf(":/");
+ StringBuilder vfsUrl = new StringBuilder();
+ vfsUrl.append("vfszip:").append(currentUrl.substring(pos+1));
+ try
+ {
+ if (isLeaf == false && vfsUrl.charAt(vfsUrl.length()-1) != '/')
+ vfsUrl.append("/");
+ setVfsUrl(new URL(vfsUrl.toString()));
+ }
+ catch(MalformedURLException ex)
+ {
+ throw new RuntimeException("ASSERTION ERROR - failed to set vfsUrl: " + vfsUrl, ex );
+ }
+
+ if(parent != null)
+ {
+ context.addChild(parent, this);
+ }
+ }
+
+ public URI toURI() throws URISyntaxException
+ {
+ return VFSUtils.toURI(url);
+ }
+
+ public long getLastModified() throws IOException
+ {
+ return getZipEntryContext().getLastModified(this);
+ }
+
+ public long getSize() throws IOException
+ {
+ return getZipEntryContext().getSize(this);
+ }
+
+ public boolean exists() throws IOException
+ {
+ return getZipEntryContext().exists(this);
+ }
+
+ public boolean isLeaf() throws IOException
+ {
+ checkClosed();
+ return getZipEntryContext().isLeaf(this);
+ }
+
+ public boolean isHidden() throws IOException
+ {
+ checkClosed();
+ return false;
+ }
+
+ public InputStream openStream() throws IOException
+ {
+ checkClosed();
+ return getZipEntryContext().openStream(this);
+ }
+
+ public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
+ {
+ return getZipEntryContext().getChildren(this, ignoreErrors);
+
+ }
+
+ public VirtualFileHandler getChild(String path) throws IOException
+ {
+ return structuredFindChild(path);
+ }
+
+
+ public VirtualFileHandler createChildHandler(String name) throws IOException
+ {
+ return getZipEntryContext().getChild(this, name);
+ }
+
+ protected void internalReplaceChild(VirtualFileHandler original, VirtualFileHandler replacement)
+ {
+ if (original instanceof AbstractVirtualFileHandler == false)
+ throw new IllegalArgumentException("Original file handler not found in this context: " + original);
+
+ getZipEntryContext().replaceChild(this, (AbstractVirtualFileHandler) original, replacement);
+ }
+
+ private ZipEntryContext getZipEntryContext()
+ {
+ return ((ZipEntryContext) getVFSContext());
+ }
+
+
+}
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,143 +0,0 @@
-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();
- }
-
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryInputStream.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,185 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * ZipEntryInputStream is part of ZipFileWrapper implementation.
+ *
+ * It wraps the stream retrieved from ZipFile.getInputStream(entry)
+ * and releases the underlying ZipFileWrapper when detecting end of use.
+ *
+ * @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
+ {
+ if (is == null)
+ throw new IllegalArgumentException("Input stream is null");
+
+ 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();
+ }
+
+ protected void finalize()
+ {
+ try
+ {
+ close();
+ }
+ catch(IOException ignored)
+ {
+ }
+ }
+
+ boolean isClosed()
+ {
+ return closed;
+ }
+
+}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java (from rev 73688, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileLockReaper.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,168 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.logging.Logger;
+
+import java.util.Iterator;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * A monitoring object that closes ZipFiles when they haven't been used for a while
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+public class ZipFileLockReaper
+{
+ private static final Logger log = Logger.getLogger(ZipFileLockReaper.class);
+
+ /**
+ * Time after which unused ZipFiles can be closed. This shouldn't be a large number
+ * to ensure smooth releasing of file locks
+ */
+ private static final int PERIOD = 5000;
+
+ /** Timer thread period */
+ private static final int TIMER_PERIOD = 1000;
+
+ /** If timer finds out there haven't been any ZipFiles open for a while it shuts down until some are (re)opened */
+ private static final int TIMER_UNUSED_PERIOD = 30000;
+
+ /** There is only one instance that serves all ZipFileWrappers */
+ private static ZipFileLockReaper singleton;
+
+ /** A list of monitored ZipFileWrappers */
+ private ConcurrentLinkedQueue monitored = new ConcurrentLinkedQueue();
+
+ /** The number of monitored ZipFileWrappers */
+ private int monitoredCount = 0;
+
+ /** Timer used for actual reaping - async closure of ZipFiles */
+ private Timer timer;
+
+ /** Timestamp of last unregister() call */
+ private long lastUsed;
+
+
+ /**
+ * Private constructor - to force retrieval through {@link #getInstance()}
+ */
+ private ZipFileLockReaper()
+ {
+
+ }
+
+ /** Factory method to be used to retrieve reference to ZipFileLockReaper */
+ public synchronized static ZipFileLockReaper getInstance()
+ {
+ if (singleton == null)
+ singleton = new ZipFileLockReaper();
+
+ return singleton;
+ }
+
+
+ /** Register a ZipFileWrapper instance with this reaper */
+ public synchronized void register(ZipFileWrapper w)
+ {
+ monitored.add(w);
+ monitoredCount++;
+ if (timer == null)
+ {
+ timer = new Timer("ZipFile Lock Reaper", true);
+ timer.schedule(new ReaperTimerTask(), TIMER_PERIOD, TIMER_PERIOD);
+ }
+ log.debug("Registered: " + w);
+ }
+
+ /** Unregister a ZipFileWrapper instance from this reaper */
+ public synchronized void unregister(ZipFileWrapper w)
+ {
+ monitored.remove(w);
+ monitoredCount--;
+ lastUsed = System.currentTimeMillis();
+ log.debug("Unregistered: " + w);
+ }
+
+
+
+ /** Timer task that does the actual reaping */
+ class ReaperTimerTask extends TimerTask
+ {
+ public void run()
+ {
+ log.debug("Timer called");
+
+ long now = System.currentTimeMillis();
+ synchronized (ZipFileLockReaper.this)
+ {
+ if (monitoredCount == 0)
+ {
+ if (now - lastUsed > TIMER_UNUSED_PERIOD)
+ {
+ timer.cancel();
+ timer = null;
+ log.debug("Cancelled the timer");
+ }
+ return;
+ }
+ }
+
+ Iterator it = monitored.iterator();
+ while (it.hasNext())
+ {
+ ZipFileWrapper w = (ZipFileWrapper) it.next();
+
+ // stream leak debug
+ /*
+ Iterator<ZipEntryInputStream> sit = w.streams.iterator();
+ while (sit.hasNext())
+ {
+ ZipEntryInputStream eis = sit.next();
+ if (!eis.isClosed())
+ {
+ System.out.println("Stream not closed: " + eis.debugCount + " - " + eis);
+ }
+ }
+ */
+
+ if (w.getReferenceCount() <= 0 && now - w.getLastUsed() > PERIOD)
+ {
+ try
+ {
+ w.closeZipFile();
+ log.debug("Asynchronously closed an unused ZipFile: " + w);
+ }
+ catch(Exception ignored)
+ {
+ log.debug("IGNORING: Failed to close ZipFile: " + w, ignored);
+ }
+ }
+ }
+ }
+ }
+
+}
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,125 +0,0 @@
-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);
- }
- }
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,232 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import org.jboss.logging.Logger;
+import org.jboss.virtual.VFSUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+
+/**
+ * ZipFileWrapper - for abstracted access to zip files on disk
+ *
+ * It releases and reacquires the underlying ZipFile as necessary
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+class ZipFileWrapper extends ZipWrapper
+{
+ private static final Logger log = Logger.getLogger(ZipFileWrapper.class);
+
+
+ private static boolean forceNoReaper;
+
+ static
+ {
+ forceNoReaper = AccessController.doPrivileged(new CheckNoReaper());
+
+ if (forceNoReaper)
+ log.info("VFS forced no-reaper-mode is enabled.");
+
+ }
+
+ private File file;
+
+ /** zip inflater wrapped around file */
+ private ZipFile zipFile;
+
+ /** true for extracted nested jars that we want removed when this wrapper is closed */
+ private boolean autoClean;
+
+ /** true if noReaper mode is forced on a per-instance basis */
+ private boolean noReaperOverride;
+
+ // used for debugging stream leaks
+ //ConcurrentLinkedQueue<ZipEntryInputStream> streams = new ConcurrentLinkedQueue<ZipEntryInputStream>();
+
+
+ ZipFileWrapper(File archive, boolean autoClean, boolean noReaperOverride)
+ {
+ this.noReaperOverride = noReaperOverride;
+ init(archive, autoClean);
+ }
+
+
+ ZipFileWrapper(URI rootPathURI, boolean autoClean, boolean noReaperOverride)
+ {
+ this.noReaperOverride = noReaperOverride;
+ File rootFile = new File(rootPathURI);
+ if(!rootFile.isFile())
+ throw new RuntimeException("File not found: " + rootFile);
+
+ init(rootFile, autoClean);
+ }
+
+ /**
+ * Extra initialization that didn't fit in constructors
+ *
+ * @param archive
+ * @param autoClean
+ */
+ private void init(File archive, boolean autoClean)
+ {
+ file = archive;
+ lastModified = file.lastModified();
+ this.autoClean = autoClean;
+ if (autoClean)
+ file.deleteOnExit();
+ }
+
+ boolean exists()
+ {
+ return file.isFile();
+ }
+
+ long getLastModified()
+ {
+ return file.lastModified();
+ }
+
+ String getName()
+ {
+ return file.getName();
+ }
+
+ long getSize()
+ {
+ return file.length();
+ }
+
+ private ZipFile ensureZipFile() throws IOException
+ {
+ if (zipFile == null)
+ {
+ zipFile = new ZipFile(file);
+ if (forceNoReaper == false && noReaperOverride == false)
+ ZipFileLockReaper.getInstance().register(this);
+ }
+
+ return zipFile;
+ }
+
+ synchronized void closeZipFile() throws IOException
+ {
+ if (zipFile != null && getReferenceCount() <= 0)
+ {
+ ZipFile zf = zipFile;
+ zipFile = null;
+ zf.close();
+ if (forceNoReaper == false && noReaperOverride == false)
+ ZipFileLockReaper.getInstance().unregister(this);
+ }
+ }
+
+ synchronized InputStream openStream(ZipEntry ent) throws IOException
+ {
+ ensureZipFile();
+ InputStream is = zipFile.getInputStream(ent);
+ if (is == null)
+ throw new IOException("Entry no longer available: " + ent.getName() + " in file " + file);
+
+ ZipEntryInputStream zis = new ZipEntryInputStream(this, is);
+
+ // debugging code
+ //streams.add(zis);
+
+ incrementRef();
+ return zis;
+ }
+
+
+ InputStream getRootAsStream() throws FileNotFoundException
+ {
+ return new FileInputStream(file);
+ }
+
+
+ synchronized void acquire() throws IOException
+ {
+ ensureZipFile();
+ incrementRef();
+ }
+
+ synchronized void release() {
+ super.release();
+ if (forceNoReaper || noReaperOverride)
+ try
+ {
+ closeZipFile();
+ }
+ catch(Exception ex)
+ {
+ log.warn("Failed to release file: " + file);
+ }
+ }
+
+ synchronized Enumeration<? extends ZipEntry> entries() throws IOException
+ {
+ return ensureZipFile().entries();
+ }
+
+ void close()
+ {
+ try
+ {
+ closeZipFile();
+ }
+ catch(Exception ignored)
+ {
+ log.warn("IGNORING: Failed to release file: " + file, ignored);
+ }
+
+ if (autoClean)
+ file.delete();
+ }
+
+ public String toString()
+ {
+ return super.toString() + " - " + file.getAbsolutePath();
+ }
+
+
+ private static class CheckNoReaper implements PrivilegedAction<Boolean>
+ {
+ public Boolean run()
+ {
+ String forceString = System.getProperty(VFSUtils.FORCE_NO_REAPER_KEY, "false");
+ return Boolean.valueOf(forceString);
+ }
+ }
+}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipStreamWrapper.java (from rev 73900, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipStreamWrapper.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipStreamWrapper.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipStreamWrapper.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,163 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.*;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+/**
+ * ZipStreamWrapper - for abstracted access to in-memory zip file
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+class ZipStreamWrapper extends ZipWrapper
+{
+ /** Raw zip archive loaded in memory */
+ private byte [] zipBytes;
+
+ /** Name */
+ private String name;
+
+ /**
+ * ZipStreamWrapper is not aware of actual zip source so it can not detect
+ * if it's been modified, like ZipFileWrapper does.
+ *
+ * @param zipStream
+ * @param lastModified passed by zip stream provider - constant value
+ * @throws IOException
+ */
+ ZipStreamWrapper(InputStream zipStream, String name, long lastModified) throws IOException
+ {
+ // read the contents into memory buffer
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ ZipEntryContext.copyStreamAndClose(zipStream, bout);
+ zipBytes = bout.toByteArray();
+
+ // TODO - delegate file meta info operations to parent?
+ this.name = name;
+ this.lastModified = lastModified;
+ }
+
+ boolean exists()
+ {
+ return true;
+ }
+
+ long getLastModified()
+ {
+ return lastModified;
+ }
+
+ String getName()
+ {
+ return name;
+ }
+
+ long getSize()
+ {
+ return zipBytes.length;
+ }
+
+ InputStream openStream(ZipEntry ent) throws IOException
+ {
+ ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
+
+ // first find the entry
+ ZipEntry entry = zis.getNextEntry();
+ while(entry != null)
+ {
+ if(entry.getName().equals(ent.getName()))
+ break;
+ entry = zis.getNextEntry();
+ }
+ if(entry == null)
+ throw new IOException("Failed to find nested jar entry: " + ent.getName() + " in zip stream: " + this.name);
+
+
+ // then read it
+ return new SizeLimitedInputStream(zis, (int) entry.getSize());
+ }
+
+ InputStream getRootAsStream() throws FileNotFoundException
+ {
+ return new ByteArrayInputStream(zipBytes);
+ }
+
+ void acquire() throws IOException
+ {
+ }
+
+ Enumeration<? extends ZipEntry> entries() throws IOException
+ {
+ return new ZipStreamEnumeration(new ZipInputStream(new ByteArrayInputStream(zipBytes)));
+ }
+
+
+ void close()
+ {
+ zipBytes = null;
+ }
+
+ public String toString()
+ {
+ return super.toString() + " - " + name;
+ }
+
+
+
+ class ZipStreamEnumeration implements Enumeration
+ {
+ private ZipInputStream zis;
+
+ private ZipEntry entry;
+
+ ZipStreamEnumeration(ZipInputStream zis) throws IOException
+ {
+ this.zis = zis;
+ entry = zis.getNextEntry();
+ }
+
+ public boolean hasMoreElements()
+ {
+ return entry != null;
+ }
+
+ public Object nextElement()
+ {
+ Object ret = entry;
+ try
+ {
+ entry = zis.getNextEntry();
+ }
+ catch (IOException ex)
+ {
+ throw new RuntimeException("Failed to retrieve next entry from zip stream", ex);
+ }
+
+ return ret;
+ }
+ }
+
+}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipWrapper.java (from rev 73900, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/plugins/context/zip/ZipWrapper.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipWrapper.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/zip/ZipWrapper.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,123 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2006, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.virtual.plugins.context.zip;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.FileNotFoundException;
+import java.util.zip.ZipEntry;
+import java.util.Enumeration;
+
+/**
+ * ZipWrapper represents abstracted access to zip archive
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+
+abstract class ZipWrapper
+{
+
+ /** last known modifyTime of the zip source */
+ protected long lastModified;
+
+ /** timestamp of last call to getLastModified()
+ * it's an expensive call - we don't do it more then once every second */
+ private long lastChecked;
+
+ /** last known activity */
+ private long lastUsed;
+
+ /** number of streams currently open on this wrapper */
+ private int refCount = 0;
+
+
+
+ /**
+ * Returns true if underlying source's lastModified time has changed since previous call
+ */
+ boolean hasBeenModified()
+ {
+ long now = System.currentTimeMillis();
+ if (now - lastChecked < 1000)
+ return false;
+
+ lastChecked = now;
+ long lm = getLastModified();
+ if (lm != lastModified)
+ {
+ lastModified = lm;
+ return true;
+ }
+
+ return false;
+ }
+
+ long getLastUsed()
+ {
+ return lastUsed;
+ }
+
+ /**
+ * Returns the number of streams currently open
+ *
+ * @return
+ */
+ int getReferenceCount()
+ {
+ return refCount;
+ }
+
+ void incrementRef()
+ {
+ refCount++;
+ lastUsed = System.currentTimeMillis();
+ }
+
+
+ synchronized void release()
+ {
+ refCount--;
+ if (refCount <= 0)
+ {
+ lastUsed = System.currentTimeMillis();
+ }
+ }
+
+ abstract void acquire() throws IOException;
+
+ abstract long getLastModified();
+
+ abstract String getName();
+
+ abstract boolean exists();
+
+ abstract long getSize();
+
+ abstract Enumeration<? extends ZipEntry> entries() throws IOException;
+
+ abstract InputStream openStream(ZipEntry ent) throws IOException;
+
+ abstract InputStream getRootAsStream() throws FileNotFoundException;
+
+ abstract void close();
+}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip)
Deleted: projects/vfs/trunk/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 2008-04-29 22:30:10 UTC (rev 72878)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -1,37 +0,0 @@
-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);
- }
-}
Copied: projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java)
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java (rev 0)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/protocol/vfszip/Handler.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,40 @@
+package org.jboss.virtual.protocol.vfszip;
+
+import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.spi.VirtualFileHandler;
+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("No VFS context found for URL: " + url);
+
+ String rootPath = ctx.getRootURI().getPath();
+ String entryPath = u.getFile().substring(rootPath.length());
+
+ VirtualFileHandler child = ctx.getChild(ctx.getRoot(), entryPath);
+ VirtualFile vf = child == null ? null : child.getVirtualFile();
+ if (vf == null)
+ throw new IOException("No VFS file found for URL: " + url);
+
+ return new VirtualFileURLConnection(u, vf);
+ }
+}
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContext.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContext.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContext.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -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
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContextFactoryLocator.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContextFactoryLocator.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/spi/VFSContextFactoryLocator.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -41,6 +41,7 @@
import org.jboss.virtual.plugins.context.file.FileSystemContextFactory;
import org.jboss.virtual.plugins.context.jar.JarContextFactory;
import org.jboss.virtual.plugins.context.memory.MemoryContextFactory;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContextFactory;
import org.jboss.virtual.plugins.context.VfsArchiveBrowserFactory;
import org.jboss.util.file.ArchiveBrowser;
@@ -250,6 +251,9 @@
if (factoryByProtocol.containsKey("vfsmemory") == false)
registerFactory(MemoryContextFactory.getInstance());
+ if (factoryByProtocol.containsKey("vfszip") == false)
+ registerFactory(ZipEntryContextFactory.getInstance());
+
initialized = true;
}
Modified: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/AbstractVFSContextTest.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -67,7 +67,7 @@
URI uri = new URI("vfs" + rootURI);
URI rfUri = rootFile.toURI();
- assertEquals(uri, rfUri);
+ assertEquals(uri.getPath(), rfUri.getPath());
}
public void testGetRoot() throws Exception
Modified: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -864,7 +864,7 @@
assertEquals("pathName", vfsPath, tmpVF.getPathName());
assertEquals("lastModified", lastModified, tmpVF.getLastModified());
assertEquals("size", size, tmpVF.getSize());
- assertEquals("url", url, tmpVF.toURL());
+ assertEquals("url", url.getPath(), tmpVF.toURL().getPath());
// TODO: these should pass
//assertEquals("isFile", true, tmpVF.isFile());
//assertEquals("isDirectory", false, tmpVF.isDirectory());
@@ -885,7 +885,7 @@
assertEquals("pathName", vfsPath, tmpVF2.getPathName());
assertEquals("lastModified", lastModified, tmpVF2.getLastModified());
assertEquals("size", size, tmpVF2.getSize());
- assertEquals("url", url, tmpVF2.toURL());
+ assertEquals("url", url.getPath(), tmpVF2.toURL().getPath());
// TODO: these should pass
//assertEquals("isFile", true, tmpVF2.isFile());
//assertEquals("isDirectory", false, tmpVF2.isDirectory());
@@ -1052,7 +1052,7 @@
assertTrue("jar1URL path ends in unpacked-outer.jar/jar1.jar!/",
jar1URL.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
VirtualFile jar1 = outerJar.findChild("jar1.jar");
- assertEquals(jar1URL, jar1.toURL());
+ assertEquals(jar1URL.getPath(), jar1.toURL().getPath());
VirtualFile packedJar = vfs.findChild("jar1.jar");
jar1URL = packedJar.findChild("org/jboss/test/vfs/support").toURL();
@@ -1081,7 +1081,7 @@
assertTrue("jar1URI path ends in unpacked-outer.jar/jar1.jar!/",
jar1URI.getPath().endsWith("unpacked-outer.jar/jar1.jar"));
VirtualFile jar1 = outerJar.findChild("jar1.jar");
- assertEquals(jar1URI, jar1.toURI());
+ assertEquals(jar1URI.getPath(), jar1.toURI().getPath());
VirtualFile packedJar = vfs.findChild("jar1.jar");
jar1URI = packedJar.findChild("org/jboss/test/vfs/support").toURI();
@@ -1244,7 +1244,7 @@
assertNotNull("tstjar != null", tstjar);
URI uri = tstjar.toURI();
URI expectedURI = new URI("vfs"+rootURL.toString()+"/path%20with%20spaces/tst.jar");
- assertEquals(uri, expectedURI);
+ assertEquals(uri.getPath(), expectedURI.getPath());
}
public static void main(String[] args) throws Exception
Modified: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java 2008-06-01 16:17:45 UTC (rev 73900)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/UnpackTestCase.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -119,7 +119,8 @@
assertReplacement(original, replacement);
VirtualFile parent = original.getParent();
VirtualFile child = parent.findChild("level2.zip");
- assertEquals(replacement, child);
+ //assertEquals(replacement, child);
+ assertEquals(replacement.toURI(), child.toURI());
VirtualFile textTwo = replacement.findChild("test2.txt");
testText(textTwo);
@@ -140,16 +141,19 @@
assertReplacement(original, replacement);
VirtualFile parent = original.getParent();
VirtualFile child = parent.findChild("level3.zip");
- assertEquals(replacement, child);
+ //assertEquals(replacement, child);
+ assertEquals(replacement.toURI(), child.toURI());
VirtualFile textThree = replacement.findChild("test3.txt");
testText(textThree);
}
- protected void assertReplacement(VirtualFile original, VirtualFile replacement) throws IOException
+ protected void assertReplacement(VirtualFile original, VirtualFile replacement) throws Exception
{
assertEquals(original.getName(), replacement.getName());
- assertEquals(original.getPathName(), replacement.getPathName());
+ // when mounting via DelegatingHandler, getPathName changes because VFSContext changes
+ //assertEquals(original.getPathName(), replacement.getPathName());
+
// it's a directory
assertEquals(0, replacement.getSize());
assertEquals(original.exists(), replacement.exists());
Copied: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java)
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java (rev 0)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryHandlerUnitTestCase.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,64 @@
+/*
+* 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.*;
+
+/**
+ * ZipEntryHandlerUnitTestCase.
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+public class ZipEntryHandlerUnitTestCase extends JARVirtualFileHandlerUnitTestCase
+{
+ public ZipEntryHandlerUnitTestCase(String name)
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(ZipEntryHandlerUnitTestCase.class);
+ }
+
+ protected VFSContext getVFSContext(String name) throws Exception
+ {
+ URL url = getRootResource(name);
+ url = JarUtils.createJarURL(url);
+ return new ZipEntryContext(url);
+ }
+
+}
\ No newline at end of file
Copied: projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java (from rev 72878, projects/vfs/branches/jar-alter-work/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java)
===================================================================
--- projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java (rev 0)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/ZipEntryVFSContextUnitTestCase.java 2008-06-01 18:25:02 UTC (rev 73901)
@@ -0,0 +1,141 @@
+/*
+* 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.jar.JarUtils;
+import org.jboss.virtual.plugins.context.zip.ZipEntryContext;
+import org.jboss.virtual.spi.VFSContext;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+
+/**
+ * ZipEntryVFSContextUnitTestCase.
+ *
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
+ * @version $Revision: 1.0 $
+ */
+public class ZipEntryVFSContextUnitTestCase extends JARVFSContextUnitTestCase
+{
+ 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);
+ }
+
+
+
+ /**
+ * Analog to the same test in {@link JARVFSContextUnitTestCase}
+ *
+ * @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());
+ }
+
+ /**
+ * Analog to the same test in {@link JARVFSContextUnitTestCase}
+ *
+ * @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());
+ }
+
+ /**
+ * Test detection of underlying jar file removal through exists()
+ *
+ * @throws Exception
+ */
+ public void testRootExists() throws Exception
+ {
+ URL url = getResource("/vfs/test/outer.jar");
+ File tmpJar = File.createTempFile("vfstest", ".jar");
+
+ InputStream is = url.openStream();
+ OutputStream os = new FileOutputStream(tmpJar);
+
+ byte [] buff = new byte[65536];
+ int count = is.read(buff);
+ while(count != -1)
+ {
+ os.write(buff, 0, count);
+ count = is.read(buff);
+ }
+ os.close();
+
+ // use noReaper so that the underlying file is not locked
+ // when we try to delete it
+ String jarUrl = tmpJar.toURL().toString() + "?noReaper=true";
+ ZipEntryContext context = new ZipEntryContext(new URL(jarUrl));
+ assertTrue("context.getRoot().exists()", context.getRoot().exists());
+
+ boolean isDeleted = tmpJar.delete();
+ assertTrue("delete tmp file: " + tmpJar, isDeleted);
+
+ assertFalse("context.getRoot().exists()", context.getRoot().exists());
+ }
+}
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list