[jboss-cvs] JBossAS SVN: r76593 - in projects/vfs/trunk/src: main/java/org/jboss/virtual/plugins/context/file and 3 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Sat Aug 2 16:08:52 EDT 2008
Author: mstruk
Date: 2008-08-02 16:08:52 -0400 (Sat, 02 Aug 2008)
New Revision: 76593
Added:
projects/vfs/trunk/src/test/resources/vfs/links/test-link.war.vfslink.properties
Removed:
projects/vfs/trunk/src/test/resources/vfs/links/war1.vfslink.properties
Modified:
projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
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/LinkHandler.java
projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextFactory.java
projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java
Log:
JBVFS-52 FileHandler::getChild() optimization
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java 2008-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSUtils.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -67,7 +67,11 @@
private static final String DEFAULT_ENCODING = "UTF-8";
/** The link */
- public static final String VFS_LINK_PREFIX = ".vfslink";
+ public static final String VFS_LINK_INFIX = ".vfslink";
+
+ /** The link properties */
+ public static final String VFS_LINK_PROPERTIES_SUFFIX = ".vfslink.properties";
+
/** The link name */
public static final String VFS_LINK_NAME = "vfs.link.name";
/** The link target */
@@ -399,7 +403,7 @@
if (name == null)
throw new IllegalArgumentException("Null name");
- return name.indexOf(VFS_LINK_PREFIX) >= 0;
+ return name.indexOf(VFS_LINK_INFIX) >= 0;
}
/**
@@ -419,7 +423,7 @@
if (name == null)
throw new IllegalArgumentException("Null name");
- if(name.endsWith(".properties"))
+ if(name.endsWith(VFS_LINK_PROPERTIES_SUFFIX))
{
List<LinkInfo> info = new ArrayList<LinkInfo>();
parseLinkProperties(is, info, props);
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java 2008-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileHandler.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -36,6 +36,7 @@
import java.util.Map;
import org.jboss.util.file.Files;
+import org.jboss.virtual.VFSUtils;
import org.jboss.virtual.plugins.context.AbstractURLHandler;
import org.jboss.virtual.plugins.context.StructuredVirtualFileHandler;
import org.jboss.virtual.spi.VirtualFileHandler;
@@ -45,6 +46,7 @@
*
* @author <a href="adrian at jboss.com">Adrian Brock</a>
* @author Scott.Stark at jboss.org
+ * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
* @version $Revision: 1.1 $
*/
public class FileHandler extends AbstractURLHandler implements StructuredVirtualFileHandler
@@ -189,6 +191,7 @@
}
else
{
+ childCache.remove(f.getName());
return true;
}
}
@@ -278,6 +281,53 @@
return structuredFindChild(path);
}
+ /**
+ * Find an existing LinkHandler or create a new one.
+ *
+ * @param name a handler name
+ * @return cached or newly created LinkHandler
+ * @throws IOException for any error
+ */
+ LinkHandler getChildLink(String name) throws IOException
+ {
+ VirtualFileHandler handler = childCache.get(name);
+ if (handler == null)
+ {
+ // check if .vfslink.properties file exists for this name
+ File file = new File(getFile(), name + VFSUtils.VFS_LINK_PROPERTIES_SUFFIX);
+ if (file.isFile())
+ {
+ FileSystemContext ctx = getVFSContext();
+ return ctx.createLinkHandler(this, file, name);
+ }
+ }
+ else if (handler instanceof LinkHandler)
+ {
+ LinkHandler link = (LinkHandler) handler;
+ if (link.exists())
+ {
+ // detect any changes in configuration
+ FileSystemContext ctx = getVFSContext();
+ try
+ {
+ return ctx.createLinkHandler(this, new File(link.toURI()), name);
+ }
+ catch (URISyntaxException e)
+ {
+ IOException ex = new IOException("Failed to convert link to URI: " + link);
+ ex.initCause(e);
+ throw ex;
+ }
+ }
+ else
+ {
+ // remove from cache
+ childCache.remove(name);
+ }
+ }
+ return null;
+ }
+
public boolean removeChild(String name) throws IOException
{
return childCache.remove(name) != null;
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-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/FileSystemContext.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -306,44 +306,13 @@
VirtualFileHandler handler = null;
if( VFSUtils.isLink(file.getName()) )
{
- Properties props = new Properties();
- FileInputStream fis = new FileInputStream(file);
- try
- {
- List<LinkInfo> links = VFSUtils.readLinkInfo(fis, file.getName(), props);
- String name = props.getProperty(VFSUtils.VFS_LINK_NAME, "link");
- handler = new LinkHandler(this, parent, uri, name, links);
- }
- catch(URISyntaxException e)
- {
- IOException ex = new IOException("Failed to parse link URIs");
- ex.initCause(e);
- throw ex;
- }
- finally
- {
- try
- {
- fis.close();
- }
- catch(IOException e)
- {
- log.debug("Exception closing file input stream: " + fis, e);
- }
- }
+ handler = createLinkHandler(parent, file, null);
}
else if (exists(file) == false && parent != null)
{
// See if we can resolve this to a link in the parent
- List<VirtualFileHandler> children = parent.getChildren(true);
- for(VirtualFileHandler vfh : children)
- {
- if( vfh.getName().equals(file.getName()) )
- {
- handler = vfh;
- break;
- }
- }
+ if (parent instanceof FileHandler)
+ handler = ((FileHandler) parent).getChildLink(file.getName());
}
else if (exists(file))
{
@@ -353,6 +322,55 @@
}
/**
+ * Create a new <tt>LinkHandler</tt> from .vfslink.properties file.
+ * A link name is derived from file name by cutting off .vfslink.properties suffix
+ *
+ * @param parent the parent handler
+ * @param file .vfslink.properties file
+ * @param linkNameCondition condition - if not null new LinkHandler will only be created if link name
+ * extracted from the file name matches linkNameCondition
+ * @return newly created <tt>LinkHandler</tt>
+ * @throws IOException for any error
+ */
+ LinkHandler createLinkHandler(VirtualFileHandler parent, File file, String linkNameCondition)
+ throws IOException
+ {
+ URI uri = file.toURI();
+ LinkHandler handler = null;
+
+ Properties props = new Properties();
+ FileInputStream fis = new FileInputStream(file);
+ try
+ {
+ List<LinkInfo> links = VFSUtils.readLinkInfo(fis, file.getName(), props);
+ String name = file.getName();
+ name = name.substring(0, name.indexOf(VFSUtils.VFS_LINK_INFIX));
+ if (name.length() == 0 || ".".equals(name) || "..".equals(name))
+ throw new IOException("Invalid link name: " + name + " (generated from file: " + file + ")");
+ if (linkNameCondition == null || linkNameCondition.equals(name))
+ handler = new LinkHandler(this, parent, uri, name, links);
+ }
+ catch(URISyntaxException e)
+ {
+ IOException ex = new IOException("Failed to parse link URIs");
+ ex.initCause(e);
+ throw ex;
+ }
+ finally
+ {
+ try
+ {
+ fis.close();
+ }
+ catch(IOException e)
+ {
+ log.debug("Exception closing file input stream: " + fis, e);
+ }
+ }
+ return handler;
+ }
+
+ /**
* Tests if file exists taking case sensitivity into account - if it's enabled
*
* @param file file to check
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java 2008-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/file/LinkHandler.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -27,6 +27,7 @@
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -96,7 +97,7 @@
public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
{
- return null;
+ return Collections.unmodifiableList(new ArrayList<VirtualFileHandler>(children.values()));
}
public boolean isLeaf() throws IOException
@@ -148,7 +149,7 @@
{
previous = linkParent;
atom = paths.get(n);
- linkParent = previous.getChild(atom);
+ linkParent = getChildPrivate(previous, atom);
if (linkParent == null)
{
linkParent = previous;
@@ -193,6 +194,15 @@
}
}
+ private VirtualFileHandler getChildPrivate(VirtualFileHandler parent, String name) throws IOException
+ {
+ // avoid infinite recursion due to LinkHandler delegation during init phase
+ if (parent instanceof LinkHandler)
+ return ((LinkHandler) parent).structuredFindChild(name);
+ else
+ return parent.getChild(name);
+ }
+
public boolean isLeaf()
{
return false;
@@ -205,7 +215,12 @@
public List<VirtualFileHandler> getChildren(boolean ignoreErrors) throws IOException
{
- return new ArrayList<VirtualFileHandler>(linkTargets.values());
+ // LinkHandler delegation: if configuration has changed, delegate to properly configured LinkHandler
+ VirtualFileHandler upToDateHandler = getParent().getChild(getName());
+ if (upToDateHandler != this)
+ return upToDateHandler.getChildren(ignoreErrors);
+ else
+ return new ArrayList<VirtualFileHandler>(linkTargets.values());
}
public VirtualFileHandler createChildHandler(String name) throws IOException
@@ -215,12 +230,22 @@
public VirtualFileHandler getChild(String path) throws IOException
{
- return structuredFindChild(path);
+ // LinkHandler delegation: if configuration has changed, delegate to properly configured LinkHandler
+ VirtualFileHandler upToDateHandler = getParent().getChild(getName());
+ if (upToDateHandler != this)
+ return upToDateHandler.getChild(path);
+ else
+ return structuredFindChild(path);
}
public boolean removeChild(String name) throws IOException
{
- return linkTargets.remove(name) != null;
+ // LinkHandler delegation: if configuration has changed, delegate to properly configured LinkHandler
+ VirtualFileHandler upToDateHandler = getParent().getChild(getName());
+ if (upToDateHandler != this)
+ return upToDateHandler.removeChild(name);
+ else
+ return linkTargets.remove(name) != null;
}
@Override
Modified: projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextFactory.java
===================================================================
--- projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextFactory.java 2008-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/main/java/org/jboss/virtual/plugins/context/memory/MemoryContextFactory.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -99,15 +99,14 @@
{
try
{
- if (url.getPath() != null && url.getPath().length() > 0)
- {
- throw new IllegalArgumentException("Root can not contain '/'");
- }
-
String rootName = url.getHost();
MemoryContext ctx = registry.get(rootName);
if (ctx == null)
{
+ if (url.getPath() != null && url.getPath().length() > 0)
+ {
+ throw new IllegalArgumentException("Root can not contain '/'");
+ }
URL ctxURL = new URL("vfsmemory://" + rootName);
ctx = new MemoryContext(ctxURL);
registry.put(rootName, ctx);
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-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/FileVFSUnitTestCase.java 2008-08-02 20:08:52 UTC (rev 76593)
@@ -21,12 +21,17 @@
*/
package org.jboss.test.virtual.test;
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
@@ -46,6 +51,7 @@
import org.jboss.test.virtual.support.ClassPathIterator;
import org.jboss.test.virtual.support.ClassPathIterator.ClassPathEntry;
import org.jboss.test.virtual.support.MetaDataMatchFilter;
+import org.jboss.virtual.MemoryFileFactory;
import org.jboss.virtual.VFS;
import org.jboss.virtual.VFSUtils;
import org.jboss.virtual.VirtualFile;
@@ -950,8 +956,8 @@
public void testVfsLinkProperties()
throws Exception
{
- URL linkURL = super.getResource("/vfs/links/war1.vfslink.properties");
- assertNotNull("vfs/links/war1.vfslink.properties", linkURL);
+ URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
+ assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
// Find resources to use as the WEB-INF/{classes,lib} link targets
URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
assertNotNull("classesURL", classesURL);
@@ -996,10 +1002,10 @@
System.setProperty("test.lib.url", libURL.toString());
// Root the vfs at the link file parent directory
- URL linkURL = super.getResource("/vfs/links/war1.vfslink.properties");
+ URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
File linkFile = new File(linkURL.toURI());
File vfsRoot = linkFile.getParentFile();
- assertNotNull("vfs/links/war1.vfslink.properties", linkURL);
+ assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
VFS vfs = VFS.getVFS(vfsRoot.toURI());
// We should find the test-link.war the link represents
@@ -1031,6 +1037,126 @@
assertEquals("archive.jar", archiveJar.getName());
}
+ /**
+ * Test configuration change detection on test-link.war link
+ * @throws Exception
+ */
+ public void testWarLinkUpdate()
+ throws Exception
+ {
+ URL classesURL = getClass().getProtectionDomain().getCodeSource().getLocation();
+ assertNotNull("classesURL", classesURL);
+ System.setProperty("test.classes.url", classesURL.toString());
+ URL libURL = super.getResource("/vfs/sundry/jar");
+ assertNotNull("libURL", libURL);
+ System.setProperty("test.lib.url", libURL.toString());
+
+ // Root the vfs at the link file parent directory
+ URL linkURL = super.getResource("/vfs/links/test-link.war.vfslink.properties");
+ File linkFile = new File(linkURL.toURI());
+ assertNotNull("vfs/links/test-link.war.vfslink.properties", linkURL);
+
+ // Setup VFS root in a temp directory
+ File root = File.createTempFile("jboss-vfs-testWarLinkUpdate", ".tmp");
+ root.delete();
+ root.mkdir();
+
+ VFS vfs = VFS.getVFS(root.toURI());
+ VirtualFile link = vfs.getChild("test-link.war");
+ assertNull("test-link.war", link);
+
+ File propsFile = new File(root, "test-link.war.vfslink.properties");
+ VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
+ link = vfs.getChild("test-link.war");
+ assertNotNull("test-link.war", link);
+
+ List<VirtualFile> children = link.getChildren();
+ assertTrue("Wrong number of link children", children.size() == 1);
+ assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 2);
+
+ // modify properties file - add more children
+ URL dynamicClassRoot = new URL("vfsmemory", ".vfslink-test", "");
+ MemoryFileFactory.createRoot(dynamicClassRoot);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintWriter webOut = new PrintWriter(new OutputStreamWriter(baos, "UTF-8"));
+ webOut.println("<?xml version=\"1.0\" ?>");
+ webOut.println("<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n" +
+ " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
+ " xsi:schemaLocation=\"http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd\"\n" +
+ " version=\"2.5\">");
+ webOut.println("</web-app>");
+ webOut.close();
+
+ URL webXmlURL = new URL(dynamicClassRoot.toExternalForm() + "/web.xml");
+ MemoryFileFactory.putFile(webXmlURL, baos.toByteArray());
+
+ PrintWriter out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(propsFile, true)));
+ out.println("vfs.link.name.2=WEB-INF/web.xml");
+ out.println("vfs.link.target.2=" + webXmlURL.toExternalForm());
+ out.close();
+
+ // You need to get a new reference to LinkHandler - to get up-to-date configuration
+ children = link.getChildren();
+ assertTrue("Wrong number of children", children.size() == 1);
+ assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 3);
+
+ // modify properties file - remove all but first
+ BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(propsFile)));
+ baos = new ByteArrayOutputStream();
+ out = new PrintWriter(new OutputStreamWriter(baos));
+ String line = in.readLine();
+ while(line != null)
+ {
+ if (line.indexOf(".0=") != -1)
+ out.println(line);
+ line = in.readLine();
+ }
+ out.close();
+ in.close();
+
+ FileOutputStream fos = new FileOutputStream(propsFile);
+ fos.write(baos.toByteArray());
+ fos.close();
+
+ children = link.getChildren();
+ assertTrue("Wrong number of children", children.size() == 1);
+ assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 1);
+
+ // modify properties file - remove all
+ fos = new FileOutputStream(propsFile);
+ fos.write(' ');
+ fos.close();
+
+ assertNotNull(link.getName() + " not null", link);
+ assertTrue(link.getName() + " exists()", link.exists());
+
+ children = link.getChildren();
+ assertTrue("Wrong number of children", children.size() == 0);
+
+ // remove properties file
+ assertTrue(propsFile.getName() + " delete()", propsFile.delete());
+
+ assertFalse(link.getName() + " exists() == false", link.exists());
+ VirtualFile oldLink = link;
+ link = vfs.getChild("test-link.war");
+ assertNull(oldLink.getName() + " is null", link);
+
+ children = vfs.getChildren();
+ assertTrue("Wrong number of children", children.size() == 0);
+
+ // put back .vfslink.properties
+ VFSUtils.copyStreamAndClose(new FileInputStream(linkFile), new FileOutputStream(propsFile));
+
+ assertTrue(oldLink.getName() + " exists()", oldLink.exists());
+ link = vfs.getChild("test-link.war");
+ assertNotNull("test-link.war", link);
+
+ children = link.getChildren();
+ assertTrue("Wrong number of children", children.size() == 1);
+ assertTrue("Wrong number of WEB-INF link children", children.get(0).getChildren().size() == 2);
+ }
+
/**
* Test that the URL of a VFS corresponding to a directory ends in '/' so that
* URLs created relative to it are under the directory. This requires that
Copied: projects/vfs/trunk/src/test/resources/vfs/links/test-link.war.vfslink.properties (from rev 76269, projects/vfs/trunk/src/test/resources/vfs/links/war1.vfslink.properties)
===================================================================
--- projects/vfs/trunk/src/test/resources/vfs/links/test-link.war.vfslink.properties (rev 0)
+++ projects/vfs/trunk/src/test/resources/vfs/links/test-link.war.vfslink.properties 2008-08-02 20:08:52 UTC (rev 76593)
@@ -0,0 +1,9 @@
+vfs.link.name=test-link.war
+# Define the name of the of link#0
+vfs.link.name.0=WEB-INF/classes
+# Define the target using a test.classes.url system property
+vfs.link.target.0=${test.classes.url}
+# Define the name of the of link#1
+vfs.link.name.1=WEB-INF/lib
+# Define the target using a test.lib.url system property
+vfs.link.target.1=${test.lib.url}
Deleted: projects/vfs/trunk/src/test/resources/vfs/links/war1.vfslink.properties
===================================================================
--- projects/vfs/trunk/src/test/resources/vfs/links/war1.vfslink.properties 2008-08-02 19:45:02 UTC (rev 76592)
+++ projects/vfs/trunk/src/test/resources/vfs/links/war1.vfslink.properties 2008-08-02 20:08:52 UTC (rev 76593)
@@ -1,9 +0,0 @@
-vfs.link.name=test-link.war
-# Define the name of the of link#0
-vfs.link.name.0=WEB-INF/classes
-# Define the target using a test.classes.url system property
-vfs.link.target.0=${test.classes.url}
-# Define the name of the of link#1
-vfs.link.name.1=WEB-INF/lib
-# Define the target using a test.lib.url system property
-vfs.link.target.1=${test.lib.url}
More information about the jboss-cvs-commits
mailing list