[jboss-cvs] JBossAS SVN: r87492 - in projects/vfs/branches/Branch_2_1: src/main/java/org/jboss/virtual and 7 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Apr 17 10:27:21 EDT 2009


Author: alesj
Date: 2009-04-17 10:27:20 -0400 (Fri, 17 Apr 2009)
New Revision: 87492

Added:
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSInputSource.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarFileURLTestCase.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarOverrideTestCase.java
Modified:
   projects/vfs/branches/Branch_2_1/pom.xml
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSUtils.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/jar/JarContext.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/temp/BasicTempInfo.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java
   projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/protocol/vfsjar/Handler.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/AbstractVFSTest.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java
   projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java
Log:
Merge from trunk

Modified: projects/vfs/branches/Branch_2_1/pom.xml
===================================================================
--- projects/vfs/branches/Branch_2_1/pom.xml	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/pom.xml	2009-04-17 14:27:20 UTC (rev 87492)
@@ -29,7 +29,7 @@
   </organization>
 
   <properties>
-    <version.jboss.common.core>2.2.9.GA</version.jboss.common.core>
+    <version.jboss.common.core>2.2.12.GA</version.jboss.common.core>
     <version.jboss.logging>2.0.5.GA</version.jboss.logging>
     <version.jboss.test>1.1.0.GA</version.jboss.test>
     <version.junit>4.4</version.junit>

Copied: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSInputSource.java (from rev 87491, projects/vfs/trunk/src/main/java/org/jboss/virtual/VFSInputSource.java)
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSInputSource.java	                        (rev 0)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSInputSource.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -0,0 +1,85 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.InputStreamReader;
+
+import org.xml.sax.InputSource;
+
+/**
+ * VFS based impl of InputSource.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class VFSInputSource extends InputSource
+{
+   private VirtualFile file;
+
+   public VFSInputSource(VirtualFile file)
+   {
+      if (file == null)
+         throw new IllegalArgumentException("Null file");
+
+      this.file = file;
+   }
+
+   @Override
+   public String getSystemId()
+   {
+      try
+      {
+         return file.toURI().toString();
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+   @Override
+   public InputStream getByteStream()
+   {
+      try
+      {
+         return file.openStream();
+      }
+      catch (IOException e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
+   @Override
+   public Reader getCharacterStream()
+   {
+      return new InputStreamReader(getByteStream());
+   }
+
+   @Override
+   public String toString()
+   {
+      return file.getPathName();
+   }
+}

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSUtils.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSUtils.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/VFSUtils.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -49,9 +49,9 @@
 import org.jboss.virtual.plugins.copy.UnjarCopyMechanism;
 import org.jboss.virtual.plugins.copy.UnpackCopyMechanism;
 import org.jboss.virtual.spi.LinkInfo;
+import org.jboss.virtual.spi.Options;
 import org.jboss.virtual.spi.VFSContext;
 import org.jboss.virtual.spi.VirtualFileHandler;
-import org.jboss.virtual.spi.Options;
 import org.jboss.virtual.spi.cache.VFSCacheFactory;
 
 /**
@@ -1087,6 +1087,12 @@
    public static String stripProtocol(URI uri)
    {
       String path = uri.getPath();
+      if(path == null)
+      {
+         String s = uri.toString();
+         if(s.startsWith("jar:file:"))
+            path = s.substring("jar:file:".length()).replaceFirst("!/", "/") + "/";
+      }
       if (path != null && path.length() > 0)
       {
          StringBuilder sb = new StringBuilder(path);

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVFSContext.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -27,11 +27,13 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.HashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 import org.jboss.logging.Logger;
 import org.jboss.virtual.VFS;
@@ -72,7 +74,7 @@
    private VirtualFileHandler rootPeer;
 
    /** The temp handlers */
-   private Map<String, TempInfo> tempInfos = new ConcurrentHashMap<String, TempInfo>();
+   private final Map<String, List<TempInfo>> tempInfos = Collections.synchronizedMap(new HashMap<String, List<TempInfo>>());
 
    /**
     * Create a new AbstractVFSContext.
@@ -378,39 +380,72 @@
 
    public void addTempInfo(TempInfo tempInfo)
    {
-      tempInfos.put(tempInfo.getPath(), tempInfo);
+      String key = tempInfo.getPath();
+      List<TempInfo> list;
+      synchronized (tempInfos)
+      {
+         list = tempInfos.get(key);
+         if (list == null)
+         {
+            list = new CopyOnWriteArrayList<TempInfo>();
+            tempInfos.put(key, list);
+         }
+      }
+      list.add(tempInfo);
    }
 
    public TempInfo getTempInfo(String path)
    {
-      TempInfo tempInfo = tempInfos.get(path);
-      if (tempInfo == null)
+      TempInfo result = null;
+      List<TempInfo> list = tempInfos.get(path);
+      if (list != null && list.isEmpty())
       {
-         return null;
+         Iterator<TempInfo> iter = list.iterator();
+         while(iter.hasNext())
+         {
+            TempInfo ti = iter.next();
+            if (ti.isValid() == false)
+            {
+               iter.remove();
+            }
+            else if (result == null)
+            {
+               result = ti;
+            }
+         }
       }
-      else if (tempInfo.isValid() == false)
-      {
-         tempInfos.remove(path);
-         return null;
-      }
-      else
-      {
-         return tempInfo;
-      }
+      return result;
    }
 
    public Iterable<TempInfo> getTempInfos()
    {
       Map<String, TempInfo> result = new TreeMap<String, TempInfo>();
-      Iterator<Map.Entry<String, TempInfo>> iter = tempInfos.entrySet().iterator();
+      Iterator<Map.Entry<String, List<TempInfo>>> iter = tempInfos.entrySet().iterator();
       while(iter.hasNext())
       {
-         Map.Entry<String, TempInfo> entry = iter.next();
-         if (entry.getValue().isValid())
+         Map.Entry<String, List<TempInfo>> entry = iter.next();
+         List<TempInfo> list = entry.getValue();
+         if (list != null && list.isEmpty() == false)
          {
-            result.put(entry.getKey(), entry.getValue());
+            Iterator<TempInfo> listIter = list.iterator();
+            while(listIter.hasNext())
+            {
+               TempInfo ti = listIter.next();
+               if (ti.isValid())
+               {
+                  String path = ti.getPath();
+                  if (result.containsKey(path) == false)
+                  {
+                     result.put(path, ti);
+                  }
+               }
+               else
+               {
+                  listIter.remove();
+               }
+            }
          }
-         else
+         if (list == null || list.isEmpty())
          {
             iter.remove();
          }
@@ -423,27 +458,33 @@
       boolean trace = log.isTraceEnabled();
       List<String> info = null;
 
-      Iterator<Map.Entry<String, TempInfo>> iter = tempInfos.entrySet().iterator();
+      Iterator<Map.Entry<String, List<TempInfo>>> iter = tempInfos.entrySet().iterator();
       while (iter.hasNext())
       {
-         Map.Entry<String, TempInfo> entry = iter.next();
+         Map.Entry<String, List<TempInfo>> entry = iter.next();
          if (entry.getKey().startsWith(path))
          {
+            List<TempInfo> list = entry.getValue();
+
             if (trace)
             {
                if (info == null)
                   info = new ArrayList<String>();
-               
-               info.add(entry.getValue().toString());
+
+               if (list != null && list.isEmpty() == false)
+                  info.add(list.toString());
             }
-            
-            try
+
+            for (TempInfo ti : list)
             {
-               entry.getValue().cleanup();
+               try
+               {
+                  ti.cleanup();                  
+               }
+               catch (Throwable ignored)
+               {
+               }
             }
-            catch (Throwable ignored)
-            {
-            }
             iter.remove();
          }
       }

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/AbstractVirtualFileHandler.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -32,7 +32,7 @@
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
 import org.jboss.logging.Logger;
 import org.jboss.virtual.VFSUtils;
@@ -103,8 +103,11 @@
    private transient String localVfsPath;
 
    /** The reference count */
-   private transient AtomicInteger references = new AtomicInteger(0);
+   private transient volatile int references;
 
+   /** The reference count updater */
+   private static final AtomicIntegerFieldUpdater<AbstractVirtualFileHandler> referencesUpdater = AtomicIntegerFieldUpdater.newUpdater(AbstractVirtualFileHandler.class, "references");
+
    /** The cached last modified */
    protected transient long cachedLastModified;
 
@@ -538,7 +541,7 @@
     */
    protected int increment()
    {
-      return references.incrementAndGet();
+      return referencesUpdater.incrementAndGet(this);
    }
 
    /**
@@ -548,7 +551,7 @@
     */
    protected int decrement()
    {
-      return references.decrementAndGet();
+      return referencesUpdater.decrementAndGet(this);
    }
 
    /**
@@ -558,7 +561,7 @@
     */
    protected void checkClosed() throws IllegalStateException 
    {
-      if (references.get() < 0)
+      if (references < 0)
          throw new IllegalStateException("Closed " + toStringLocal());
    }
 
@@ -569,7 +572,7 @@
     */
    protected int getReferences()
    {
-      return references.get();
+      return references;
    }
 
    public void cleanup()
@@ -596,7 +599,7 @@
       }
       finally
       {
-         references.decrementAndGet();   
+         referencesUpdater.decrementAndGet(this);
       }
    }
 
@@ -833,7 +836,7 @@
       this.name = (String) fields.get("name", null);
       VFSContextFactory factory = VFSContextFactoryLocator.getFactory(rootURI);
       this.context = factory.getVFS(rootURI);
-      this.references = new AtomicInteger(0);
+      this.references = 0;
       this.vfsUrl = (URL)fields.get("vfsUrl", null);
    }
 }

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/jar/JarContext.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/jar/JarContext.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/jar/JarContext.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -87,6 +87,12 @@
       String jarName = extractJarName(urlStr);
       String entryPath = urlStr;
       entryPath = entryPath(entryPath);
+      // make sure that JarHandler.initJar works on the jar itself
+      if(entryPath != null)
+      {
+         String s = url.toExternalForm();
+         url = new URL(s.substring(0, s.length() - entryPath.length()));
+      }
       JarHandler jar =  new JarHandler(this, parent, url, jarName);
       if (entryPath == null)
          return jar;
@@ -118,6 +124,12 @@
       return entryName;
    }
 
+   /**
+    * Extract jar name.
+    *
+    * @param urlStr the url string
+    * @return jar name
+    */
    public static String extractJarName(String urlStr)
    {
       String jarName = urlStr;

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/temp/BasicTempInfo.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/temp/BasicTempInfo.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/temp/BasicTempInfo.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -65,9 +65,16 @@
    public void cleanup()
    {
       if (handler != null)
+      {
          handler.cleanup();
+      }
       else if (file != null && file.exists())
+      {
          Files.delete(file);
+      }
+      // release
+      handler = null;
+      file = null;
    }
 
    public VirtualFileHandler getHandler()

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipEntryContext.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -41,8 +41,8 @@
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
+import java.util.LinkedHashMap;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -94,6 +94,7 @@
  *
  * @author <a href="strukelj at parsek.net">Marko Strukelj</a>
  * @author <a href="ales.justin at jboss.org">Ales Justin</a>
+ * @author <a href="david.lloyd at jboss.com">David M. Lloyd</a>
  * @version $Revision: 1.0 $
  */
 public class ZipEntryContext extends AbstractVFSContext
@@ -114,6 +115,9 @@
          log.info("VFS force nested jars copy-mode is enabled.");
    }
 
+   /** The empty bytes const */
+   private static final byte[] NO_BYTES = new byte[0];
+
    /** Abstracted access to zip archive - either ZipFileWrapper or ZipStreamWrapper */
    private ZipWrapper zipSource;
 
@@ -520,8 +524,10 @@
                   {
                      path = getPath(context, entryName);
                      TempInfo ti = context.getTempInfo(path);
-                     if (ti != null)
+                     if (ti != null && ti.isValid())
+                     {
                         dest = ti.getTempFile();
+                     }
                   }
 
                   boolean createNewTempInfo = (dest == null || dest.exists() == false);
@@ -1061,7 +1067,7 @@
       }
 
       if(ei.entry == null)
-         return new ByteArrayInputStream(new byte[0]);
+         return new ByteArrayInputStream(NO_BYTES);
 
       return getZipSource().openStream(ei.entry);
    }
@@ -1169,7 +1175,7 @@
       private ZipEntry entry;
 
       /** a list of children */
-      private List<AbstractVirtualFileHandler> children;
+      private Map<String, AbstractVirtualFileHandler> children;
 
       /**
        * EntryInfo constructor
@@ -1193,7 +1199,7 @@
          if (children == null)
             return Collections.emptyList();
 
-         return new LinkedList<VirtualFileHandler>(children);
+         return new ArrayList<VirtualFileHandler>(children.values());
       }
 
       /**
@@ -1206,15 +1212,9 @@
       {
          if (children != null)
          {
-            int i = 0;
-            for (AbstractVirtualFileHandler child : children)
-            {
-               if (child.getName().equals(original.getName()))
-               {
-                  children.set(i, replacement);
-                  break;
-               }
-               i++;
+            final String name = original.getName();
+            if (children.containsKey(name)) {
+               children.put(name, replacement);
             }
          }
       }
@@ -1237,24 +1237,9 @@
       {
          if (children == null)
          {
-            children = new LinkedList<AbstractVirtualFileHandler>();
+            children = new LinkedHashMap<String, 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);
+         children.put(child.getName(), child);
       }
    }
 

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/context/zip/ZipFileWrapper.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -310,29 +310,36 @@
       if (exists == false)
          return false;
 
-      long endOfGrace = System.currentTimeMillis() + gracePeriod;
-      do
+      boolean interrupted = Thread.interrupted();
+      try
       {
-         closeZipFile();
-         ZipFileLockReaper.getInstance().deleteFile(this);
-         try
+         long endOfGrace = System.currentTimeMillis() + gracePeriod;
+         do
          {
-            if (file.exists() && file.delete() == false)
-               Thread.sleep(100);
-            else
-               return true;
+            closeZipFile();
+            ZipFileLockReaper.getInstance().deleteFile(this);
+            try
+            {
+               if (file.exists() && file.delete() == false)
+                  Thread.sleep(100);
+               else
+                  return true;
+            }
+            catch (InterruptedException e)
+            {
+               interrupted = true;
+               return file.exists() == false || file.delete();
+            }
          }
-         catch (InterruptedException e)
-         {
-            IOException ioe = new IOException("Interrupted: " + e);
-            ioe.initCause(e);
-            throw ioe;
-         }
+         while(System.currentTimeMillis() < endOfGrace);
       }
-      while(System.currentTimeMillis() < endOfGrace);
+      finally
+      {
+         if (interrupted)
+            Thread.currentThread().interrupt();
+      }
 
-      file.delete();
-      return file.exists() == false;
+      return file.delete();
    }
 
    protected synchronized void recomposeZip(OutputStream baos, String path) throws IOException

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/plugins/vfs/helpers/PathTokenizer.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -31,6 +31,7 @@
  * 
  * @author <a href="adrian at jboss.com">Adrian Brock</a>
  * @author <a href="ales.justin at jboss.com">Ales Justin</a>
+ * @author <a href="david.lloyd at jboss.com">David M. Lloyd</a>
  * @version $Revision: 1.1 $
  */
 @SuppressWarnings({"StringEquality"})
@@ -48,6 +49,12 @@
    /** Flag permission */
    private static Permission flagPermission = new RuntimePermission(PathTokenizer.class.getName() + ".setErrorOnSuspiciousTokens");
 
+   /** Token states */
+   private static final int STATE_INITIAL = 0;
+   private static final int STATE_NORMAL = 1;
+   private static final int STATE_MAYBE_CURRENT_PATH = 2;
+   private static final int STATE_MAYBE_REVERSE_PATH = 3;
+
    /**
     * Utility class
     */
@@ -85,85 +92,115 @@
    }
 
    /**
-    * Get the tokens
+    * Get the tokens that comprise this path.
     * 
     * @param path the path
     * @return the tokens or null if the path is empty
-    * @throws IllegalArgumentException if the path is null, it is empty or it is a relative path
+    * @throws IllegalArgumentException if the path is null, or if this class is configured to reject
+    *    so-called "suspicious" tokens (files that start with "." which are not one of the two special
+    *    directories "." or "..")
     */
    public static List<String> getTokens(String path)
    {
       if (path == null)
          throw new IllegalArgumentException("Null path");
 
-      char[] chars = path.toCharArray();
-      StringBuilder buffer = new StringBuilder();
+      int start = -1, length = path.length(), state = STATE_INITIAL;
+      char ch;
       List<String> list = new ArrayList<String>();
-      String specialToken = null;
 
-      for (int index=0; index < chars.length; index++)
-      {
-         char ch = chars[index];
-
-         if (ch == '/')
-         {
-            if (index > 0)
-            {
-               if (buffer.length() == 0 && specialToken == null)
-                  continue;
-
-               if (specialToken != null)
-                  list.add(specialToken);
-               else
-                  list.add(buffer.toString());
-
-               // reset
-               buffer.setLength(0);
-               specialToken = null;
+      for (int index = 0; index < length; index ++) {
+         ch = path.charAt(index);
+         switch (ch) {
+            case '/': {
+               switch (state) {
+                  case STATE_INITIAL: {
+                     // skip extra leading /
+                     continue;
+                  }
+                  case STATE_MAYBE_CURRENT_PATH: {
+                     // it's '.'
+                     list.add(CURRENT_PATH);
+                     state = STATE_INITIAL;
+                     continue;
+                  }
+                  case STATE_MAYBE_REVERSE_PATH: {
+                     // it's '..'
+                     list.add(REVERSE_PATH);
+                     state = STATE_INITIAL;
+                     continue;
+                  }
+                  case STATE_NORMAL: {
+                     // it's just a normal path segment
+                     list.add(path.substring(start, index));
+                     state = STATE_INITIAL;
+                     continue;
+                  }
+               }
+               continue;
             }
-         }
-         else if (ch == '.')
-         {
-            int bufferLength = buffer.length();
-
-            if (specialToken == null && bufferLength == 0)
-               specialToken = CURRENT_PATH;
-            else if (specialToken == CURRENT_PATH && bufferLength == 0)
-               specialToken = REVERSE_PATH;
-            else if (specialToken == REVERSE_PATH && bufferLength == 0)
-            {
-               if (errorOnSuspiciousTokens)
-                  throw new IllegalArgumentException("Illegal token (" + specialToken + ch + ") in path: " + path);
-
-               buffer.append(specialToken).append(ch);
-               specialToken = null;
+            case '.': {
+               switch (state) {
+                  case STATE_INITIAL: {
+                     // . is the first char; might be a special token
+                     state = STATE_MAYBE_CURRENT_PATH;
+                     start = index;
+                     continue;
+                  }
+                  case STATE_MAYBE_CURRENT_PATH: {
+                     // the second . in a row...
+                     state = STATE_MAYBE_REVERSE_PATH;
+                     continue;
+                  }
+                  case STATE_MAYBE_REVERSE_PATH: {
+                     // the third . in a row, guess it's just a weird path name
+                     if (errorOnSuspiciousTokens) {
+                        throw new IllegalArgumentException("Illegal suspicious token in path: " + path);
+                     }
+                     state = STATE_NORMAL;
+                     continue;
+                  }
+               }
+               continue;
             }
-            else
-               buffer.append(ch);
-         }
-         else
-         {
-            // token starts with '.' or '..', but also has some path after that
-            if (specialToken != null)
-            {
-               // we don't allow tokens after '..'
-               if (errorOnSuspiciousTokens && specialToken == REVERSE_PATH)
-                  throw new IllegalArgumentException("Illegal token (" + specialToken + ch + ") in path: " + path);
-
-               // after '.' more path is legal == unix hidden directories
-               buffer.append(specialToken);
-               specialToken = null;
+            default: {
+               switch (state) {
+                  case STATE_INITIAL: {
+                     state = STATE_NORMAL;
+                     start = index;
+                     continue;
+                  }
+                  case STATE_MAYBE_CURRENT_PATH:
+                  case STATE_MAYBE_REVERSE_PATH: {
+                     if (errorOnSuspiciousTokens) {
+                        throw new IllegalArgumentException("Illegal suspicious token in path: " + path);
+                     }
+                     state = STATE_NORMAL;
+                  }
+               }
             }
-            buffer.append(ch);
          }
       }
+      // handle the last token
+      switch (state) {
+         case STATE_INITIAL: {
+            // trailing /
+            break;
+         }
+         case STATE_MAYBE_CURRENT_PATH: {
+            list.add(CURRENT_PATH);
+            break;
+         }
+         case STATE_MAYBE_REVERSE_PATH: {
+            list.add(REVERSE_PATH);
+            break;
+         }
+         case STATE_NORMAL: {
+            list.add(path.substring(start));
+            break;
+         }
+      }
 
-      // add last token
-      if (specialToken != null)
-         list.add(specialToken);
-      else if (buffer.length() > 0)
-         list.add(buffer.toString());
-
       return list;
    }
    

Modified: projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/protocol/vfsjar/Handler.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/protocol/vfsjar/Handler.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/main/java/org/jboss/virtual/protocol/vfsjar/Handler.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -40,7 +40,15 @@
    {
       String urlString = u.toString();
       int index = urlString.indexOf("!/");
-      String file = urlString.substring(3, index + 2); // strip out vfs
+      // because we trim the url in JarContext.createVirtualFileHandler we can
+      // actually end up with a vfsjar:file: URL which does not point to an entry.
+      String file;
+      // strip out vfs
+      if(index == -1)
+         file = urlString.substring(3);
+      else
+         file = urlString.substring(3, index + 2);
+      
       String path = urlString.substring(index + 2);
       URL url = new URL(file);
       return new VirtualFileURLConnection(u, url, path);

Modified: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/AbstractVFSTest.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/AbstractVFSTest.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/AbstractVFSTest.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -22,6 +22,8 @@
 package org.jboss.test.virtual.test;
 
 import java.net.URL;
+import java.util.Map;
+import java.lang.reflect.Field;
 
 import junit.framework.AssertionFailedError;
 import org.jboss.test.BaseTestCase;
@@ -65,6 +67,21 @@
       this.forceNoReaper = forceNoReaper;
    }
 
+   @SuppressWarnings("unchecked")
+   protected static Map<String, VFSContextFactory> getFactoryByProtocol()
+   {
+      try
+      {
+         Field field = VFSContextFactoryLocator.class.getDeclaredField("factoryByProtocol");
+         field.setAccessible(true);
+         return (Map<String, VFSContextFactory>) field.get(null);
+      }
+      catch (Exception e)
+      {
+         throw new RuntimeException(e);
+      }
+   }
+
    protected void setUp() throws Exception
    {
       super.setUp();

Copied: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarFileURLTestCase.java (from rev 87491, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/JarFileURLTestCase.java)
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarFileURLTestCase.java	                        (rev 0)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarFileURLTestCase.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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 java.io.InputStream;
+import java.net.URL;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VirtualFile;
+
+/**
+ * @author <a href="mailto:cdewolf at redhat.com">Carlo de Wolf</a>
+ * @version $Revision: $
+ */
+public class JarFileURLTestCase extends AbstractVFSTest
+{
+   public JarFileURLTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite()
+   {
+      return suite(JarFileURLTestCase.class);
+   }
+
+   public void testStreamDirectAndURL() throws Exception
+   {
+      URL url = getResource("/vfs/test/jar1.jar");
+      URL manifestURL = new URL("jar:" + url.toExternalForm() + "!/META-INF/MANIFEST.MF");
+      
+      // first we ask for a jar:file: resource
+      
+      VirtualFile manifest = VFS.getRoot(manifestURL);
+      
+      InputStream in = manifest.openStream();
+      in.close();
+      
+      in = manifest.toURL().openStream();
+      in.close();
+   }
+}

Copied: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarOverrideTestCase.java (from rev 87491, projects/vfs/trunk/src/test/java/org/jboss/test/virtual/test/JarOverrideTestCase.java)
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarOverrideTestCase.java	                        (rev 0)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/JarOverrideTestCase.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -0,0 +1,99 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * 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 java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.net.URL;
+
+import junit.framework.Test;
+import org.jboss.virtual.VFS;
+import org.jboss.virtual.VFSUtils;
+import org.jboss.virtual.VirtualFile;
+
+/**
+ * Test jar file override.
+ *
+ * @author ales.justin at jboss.org
+ */
+public class JarOverrideTestCase extends AbstractVFSTest
+{
+   public JarOverrideTestCase(String name)
+   {
+      super(name, true, false);
+   }
+
+   public static Test suite()
+   {
+      return suite(JarOverrideTestCase.class);
+   }
+
+   @SuppressWarnings("deprecation")
+   public void testOverride() throws Exception
+   {
+      URL topURL = getResource("/vfs/test/nested/nested.jar");
+      URI topURI = topURL.toURI();
+      File source = new File(topURI);
+
+      // create temp so we can override it, not worrying about other tests
+      File tempDest = File.createTempFile("nested", "-temp.jar");
+      tempDest.deleteOnExit();
+      copy(source, tempDest);
+      long ts1 = tempDest.lastModified();
+
+      VirtualFile nested = VFS.createNewRoot(tempDest.toURI());
+      VirtualFile complex = nested.findChild("complex.jar");
+      // mock war unjaring
+      VirtualFile unjared = VFSUtils.unjar(complex);
+      assertNotSame(complex, unjared);
+
+      // wait 1sec+
+      Thread.sleep(1500l);
+
+      // override
+      copy(source, tempDest);
+      long ts2 = tempDest.lastModified();
+      // was it really overridden
+      assertFalse(ts1 == ts2);
+
+      // undeploy
+      nested.cleanup();
+      complex.cleanup();
+      // check we really deleted unjared temp
+      URL url = VFSUtils.getRealURL(unjared);
+      File unjaredTemp = new File(url.toURI());
+      assertFalse(unjaredTemp.exists());
+
+      // 2nd pass to mock
+      complex = nested.findChild("complex.jar");
+      // this is where JBAS-6715 fails
+      unjared = VFSUtils.unjar(complex);
+      assertNotSame(complex, unjared);
+   }
+
+   protected void copy(File source, File dest) throws Exception
+   {
+      VFSUtils.copyStreamAndClose(new FileInputStream(source), new FileOutputStream(dest));
+   }
+}
\ No newline at end of file

Modified: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSAllTestSuite.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -58,6 +58,7 @@
       suite.addTest(FileVFSContextUnitTestCase.suite());
       suite.addTest(FileVirtualFileHandlerUnitTestCase.suite());
       // jars
+      suite.addTest(JarFileURLTestCase.suite());
       suite.addTest(JARCacheUnitTestCase.suite());
       suite.addTest(CopyJARCacheUnitTestCase.suite());
       suite.addTest(JARVFSContextUnitTestCase.suite());
@@ -68,6 +69,7 @@
       suite.addTest(CopyJAREntryTestCase.suite());
       suite.addTest(ZipEntryHandlerUnitTestCase.suite());
       suite.addTest(ZipEntryVFSContextUnitTestCase.suite());
+      suite.addTest(JarOverrideTestCase.suite());
       // contexts
       suite.addTest(AssembledContextTestCase.suite());
       suite.addTest(MemoryTestCase.suite());

Modified: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSCacheTest.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -21,6 +21,7 @@
 */
 package org.jboss.test.virtual.test;
 
+import java.io.IOException;
 import java.net.URI;
 import java.net.URL;
 import java.util.Collections;
@@ -28,7 +29,9 @@
 
 import org.jboss.virtual.VFS;
 import org.jboss.virtual.VirtualFile;
+import org.jboss.virtual.plugins.context.jar.JarContextFactory;
 import org.jboss.virtual.spi.VFSContext;
+import org.jboss.virtual.spi.VFSContextFactory;
 import org.jboss.virtual.spi.cache.CacheStatistics;
 import org.jboss.virtual.spi.cache.VFSCache;
 import org.jboss.virtual.spi.cache.VFSCacheFactory;
@@ -191,6 +194,58 @@
       }
    }
 
+   /**
+    * Test jar path.
+    *
+    * @throws Exception for any error
+    */
+   public void testJarPath() throws Exception
+   {
+      // to circumvent another bug in VFS
+      Map<String, VFSContextFactory> factoryByProtocol = getFactoryByProtocol();
+      VFSContextFactory oldFactory = factoryByProtocol.put("jar", new JarContextFactory());
+      
+      VFSCache cache = createCache();
+      cache.start();
+      try
+      {
+         VFSCacheFactory.setInstance(cache);
+         try
+         {
+            configureCache(cache);
+
+            URL url = getResource("/vfs/test/jar1.jar");
+            URL manifestURL = new URL("jar:" + url.toExternalForm() + "!/META-INF/MANIFEST.MF");
+            
+            // first we ask for a jar:file: resource
+            
+            VirtualFile manifest = VFS.getRoot(manifestURL);
+
+            assertNotNull(manifest);
+            
+            // then we ask for a file: resource
+            
+            VirtualFile jar = VFS.getRoot(url);
+            
+            assertNotNull(jar);
+         }
+         catch(IOException e)
+         {
+            fail("failed to get the proper files: " + e.getMessage());
+         }
+         finally
+         {
+            VFSCacheFactory.setInstance(null);
+         }
+      }
+      finally
+      {
+         factoryByProtocol.put("jar", oldFactory);
+         
+         stopCache(cache);
+      }
+   }
+
    private class WrapperVFSCache implements VFSCache
    {
       private VFSCache delegate;

Modified: projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java
===================================================================
--- projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	2009-04-17 12:17:44 UTC (rev 87491)
+++ projects/vfs/branches/Branch_2_1/src/test/java/org/jboss/test/virtual/test/VFSUtilTestCase.java	2009-04-17 14:27:20 UTC (rev 87492)
@@ -27,6 +27,7 @@
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
+
 import org.jboss.virtual.VFS;
 import org.jboss.virtual.VFSUtils;
 import org.jboss.virtual.VirtualFile;
@@ -117,4 +118,19 @@
       // TODO - JBVFS-77 --> do proper tests!
 	   assertTrue(realURL.toExternalForm().startsWith("file:"));
    }
+   
+   public void testStripProtocol() throws Exception
+   {
+      URL url = getResource("/vfs/test/jar1.jar");
+      
+      VirtualFile manifest = VFS.getRoot(url).getChild("META-INF/MANIFEST.MF");
+      String expected = VFSUtils.stripProtocol(manifest.toURI());
+      
+      URL manifestURL = new URL("jar:" + url.toExternalForm() + "!/META-INF/MANIFEST.MF");
+      System.out.println(manifestURL);
+      System.out.println(manifestURL.toURI());
+      String actual = VFSUtils.stripProtocol(manifestURL.toURI());
+      
+      assertEquals("path from jar:file: url is not usable", expected, actual);
+   }
 }
\ No newline at end of file




More information about the jboss-cvs-commits mailing list