[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