You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2006/08/12 06:04:35 UTC

svn commit: r430965 - in /geronimo/branches/1.1.1/modules/kernel/src: java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java

Author: djencks
Date: Fri Aug 11 21:04:34 2006
New Revision: 430965

URL: http://svn.apache.org/viewvc?rev=430965&view=rev
Log:
GERONIMO-2305 fix JarFileUrlStreamHandler to work with any entry in the jarfile

Modified:
    geronimo/branches/1.1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java
    geronimo/branches/1.1.1/modules/kernel/src/test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java

Modified: geronimo/branches/1.1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java?rev=430965&r1=430964&r2=430965&view=diff
==============================================================================
--- geronimo/branches/1.1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java (original)
+++ geronimo/branches/1.1.1/modules/kernel/src/java/org/apache/geronimo/kernel/classloader/JarFileUrlStreamHandler.java Fri Aug 11 21:04:34 2006
@@ -16,13 +16,15 @@
  */
 package org.apache.geronimo.kernel.classloader;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
-import java.net.MalformedURLException;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
-import java.io.File;
 
 /**
  * @version $Rev$ $Date$
@@ -56,11 +58,48 @@
         this.expectedUrl = expectedUrl;
     }
 
-    public URLConnection openConnection(URL url) throws MalformedURLException {
+    public URLConnection openConnection(URL url) throws IOException {
         if (expectedUrl == null) throw new IllegalStateException("expectedUrl was not set");
 
-        // alternatively we could return a connection using the normal jar url connection
-        if (!expectedUrl.equals(url)) throw new IllegalArgumentException("Expected url [" + expectedUrl + "], but was [" + url + "]");
+        // the caller copied the URL reusing a stream handler from a previous call
+        if (!expectedUrl.equals(url)) {
+            // the new url is supposed to be within our context, so it must have a jar protocol
+            if (!url.getProtocol().equals("jar")) {
+                throw new IllegalArgumentException("Unsupported protocol " + url.getProtocol());
+            }
+
+            // split the path at "!/" into the file part and entry part
+            String path = url.getPath();
+            String[] chunks = path.split("!/", 2);
+
+            // if we only got only one chunk, it didn't contain the required "!/" delimiter
+            if (chunks.length == 1) {
+                throw new MalformedURLException("Url does not contain a '!' character: " + url);
+            }
+
+            String file = chunks[0];
+            String entryPath = chunks[1];
+
+            // this handler only supports jars on the local file system
+            if (!file.startsWith("file:")) {
+                // let the system handler deal with this
+                return new URL(url.toExternalForm()).openConnection();
+            }
+            file = file.substring("file:".length());
+
+            // again the new url is supposed to be within our context so it must reference the same jar file
+            if (!jarFile.getName().equals(file)) {
+                // let the system handler deal with this
+                return new URL(url.toExternalForm()).openConnection();
+            }
+
+            // get the entry
+            JarEntry newEntry = jarFile.getJarEntry(entryPath);
+            if (newEntry == null) {
+                throw new FileNotFoundException("Entry not found: " + url);
+            }
+            return new JarFileUrlConnection(url, jarFile, newEntry);
+        }
 
         return new JarFileUrlConnection(url, jarFile, jarEntry);
     }

Modified: geronimo/branches/1.1.1/modules/kernel/src/test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1.1/modules/kernel/src/test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java?rev=430965&r1=430964&r2=430965&view=diff
==============================================================================
--- geronimo/branches/1.1.1/modules/kernel/src/test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java (original)
+++ geronimo/branches/1.1.1/modules/kernel/src/test/org/apache/geronimo/kernel/classloader/UrlResourceFinderTest.java Fri Aug 11 21:04:34 2006
@@ -18,6 +18,7 @@
 package org.apache.geronimo.kernel.classloader;
 
 import java.net.URL;
+import java.net.MalformedURLException;
 import java.util.Enumeration;
 import java.util.zip.ZipEntry;
 import java.util.jar.JarOutputStream;
@@ -27,16 +28,20 @@
 import java.io.IOException;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileNotFoundException;
 
 import junit.framework.TestCase;
 
 /**
- * @version $Rev:$ $Date:$
+ * @version $Rev$ $Date$
  */
 public class UrlResourceFinderTest extends TestCase {
+    private File basedir = new File(System.getProperty("basedir"));
     private File jarFile;
     private Manifest manifest;
     private Attributes resourceAttributes;
+    private File alternateJarFile;
+    private File testResource;
 
     /**
      * There are 2 "jars" with a "resource" inside.  Make sure the enumeration has exactly 2 elements and
@@ -47,7 +52,7 @@
     public void testResourceEnumeration() throws Exception {
         URL jar1 = new File("src/test-data/resourceFinderTest/jar1/").toURL();
         URL jar2 = new File("src/test-data/resourceFinderTest/jar2/").toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar1, jar2});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar1, jar2});
 
         Enumeration enumeration = resourceFinder.findResources("resource");
 
@@ -69,7 +74,7 @@
 
     public void testDirectoryResource() throws Exception {
         URL jar = new File("src/test-data/resourceFinderTest/jar1/").toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
 
         ResourceHandle resource = resourceFinder.getResource("resource");
         assertNotNull(resource);
@@ -108,7 +113,7 @@
 
     public void testJarResource() throws Exception {
         URL jar = jarFile.toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
 
         ResourceHandle resource = resourceFinder.getResource("resource");
         assertNotNull(resource);
@@ -147,7 +152,7 @@
 
     public void testAddURL() throws Exception {
         URL jar1 = new File("src/test-data/resourceFinderTest/jar1/").toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar1});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar1});
 
         Enumeration enumeration = resourceFinder.findResources("resource");
 
@@ -195,7 +200,7 @@
     public void testConcurrentAddURL() throws Exception {
         URL jar1 = new File("src/test-data/resourceFinderTest/jar1/").toURL();
         URL jar2 = new File("src/test-data/resourceFinderTest/jar2/").toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar1, jar2});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar1, jar2});
 
         Enumeration enumeration = resourceFinder.findResources("resource");
 
@@ -238,16 +243,121 @@
 
     public void testDirectoryDestroy() throws Exception {
         URL jar = new File("src/test-data/resourceFinderTest/jar1/").toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
         assertDestroyed(resourceFinder, "resource1", null);
     }
 
     public void testJarDestroy() throws Exception {
         URL jar = jarFile.toURL();
-        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[] {jar});
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
         assertDestroyed(resourceFinder, "resource3", manifest);
     }
 
+    public void testUrlCopy() throws Exception {
+        URL jar = jarFile.toURL();
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
+
+        // get the resource
+        URL resource = resourceFinder.findResource("resource");
+        assertNotNull(resource);
+        assertEquals("resource3", toString(resource.openStream()));
+
+        // copy resource with string
+        URL stringCopy = new URL(resource.toExternalForm());
+        assertEquals("resource3", toString(stringCopy.openStream()));
+
+        // copy resource perserving the url handler
+        URL handlerCopy = new URL(resource, resource.toExternalForm());
+        assertEquals("resource3", toString(handlerCopy.openStream()));
+
+        // access the other resource using the original url as a starting point
+        URL other = new URL(resource, "jar3");
+        assertEquals("jar3", toString(other.openStream()));
+    }
+
+    public void testUrlAccess() throws Exception {
+        URL jar = jarFile.toURL();
+        UrlResourceFinder resourceFinder = new UrlResourceFinder(new URL[]{jar});
+
+        // get geronimo url from the resource finder
+        URL geronimoUrl = resourceFinder.findResource("resource");
+        assertNotNull(geronimoUrl);
+        assertEquals("resource3", toString(geronimoUrl.openStream()));
+
+        // get a system url by copying the url by string
+        URL systemUrl = new URL(geronimoUrl.toExternalForm());
+        assertEquals("resource3", toString(systemUrl.openStream()));
+
+        // verify both can see the jar3 file withing the jar file
+        assertEquals("jar3", toString(new URL(systemUrl, "jar3").openStream()));
+        assertEquals("jar3", toString(new URL(geronimoUrl, "jar3").openStream()));
+
+        // verify both can see the jar3 file withing the jar file using a full url spec
+        String mainEntry = "jar:" + jarFile.toURL().toExternalForm() + "!/jar3";
+        assertEquals("jar3", toString(new URL(systemUrl, mainEntry).openStream()));
+        assertEquals("jar3", toString(new URL(geronimoUrl, mainEntry).openStream()));
+
+        // verify both throw a FileNotFoundExcetion for an unknown file
+        try {
+            new URL(systemUrl, "unknown").openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+        try {
+            new URL(geronimoUrl, "unknown").openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+
+        // verify both can see the alternate jar
+        String alternateEntry = "jar:" + alternateJarFile.toURL().toExternalForm() + "!/jar4";
+        assertEquals("jar4", toString(new URL(systemUrl, alternateEntry).openStream()));
+        assertEquals("jar4", toString(new URL(geronimoUrl, alternateEntry).openStream()));
+
+        // verify both throw a FileNotFoundExcetion for an unknown entry in the alternate file
+        String alternateUnknownEntry = "jar:" + alternateJarFile.toURL().toExternalForm() + "!/unknown";
+        try {
+            new URL(systemUrl, alternateUnknownEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+        try {
+            new URL(geronimoUrl, alternateUnknownEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+
+        // verify both work an excepton for a non-jar entry
+        assertEquals("testResource", toString(new URL(systemUrl, testResource.toURL().toExternalForm()).openStream()));
+        assertEquals("testResource", toString(new URL(geronimoUrl, testResource.toURL().toExternalForm()).openStream()));
+
+        // verify both fail for a spec without a !/
+        String badEntry = "jar:" + alternateJarFile.toURL().toExternalForm();
+        try {
+            new URL(systemUrl, badEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (MalformedURLException expected) {
+        }
+        try {
+            new URL(geronimoUrl, badEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (MalformedURLException expected) {
+        }
+
+        // verify both throw FileNotFoundException for a nested jar file
+        badEntry = "jar:" + alternateJarFile.toURL().toExternalForm() + "!/foo.jar!/bar";
+        try {
+            new URL(systemUrl, badEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+        try {
+            new URL(geronimoUrl, badEntry).openStream();
+            fail("Expected a FileNotFoundException");
+        } catch (FileNotFoundException expected) {
+        }
+    }
+
     public void assertDestroyed(UrlResourceFinder resourceFinder, String resourceValue, Manifest expectedManifest) throws Exception {
         ResourceHandle resource = resourceFinder.getResource("resource");
         assertNotNull(resource);
@@ -267,7 +377,6 @@
         URL directUrlCopy = new URL(directUrl.toExternalForm());
         assertEquals(resourceValue, toString(directUrlCopy.openStream()));
 
-
         // destroy
         resourceFinder.destroy();
 
@@ -327,6 +436,9 @@
     protected void setUp() throws Exception {
         super.setUp();
 
+        //
+        // Build a simple Jar file to test with
+        //
         manifest = new Manifest();
         Attributes mainAttributes = manifest.getMainAttributes();
         mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
@@ -335,14 +447,28 @@
         resourceAttributes.putValue("drink", "margarita");
         manifest.getEntries().put("resource", resourceAttributes);
 
-        jarFile = new File("target/resourceFinderTest.jar");
-        System.out.println(jarFile.getAbsolutePath());
+        File targetDir = new File(basedir, "target");
+        jarFile = new File(targetDir, "resourceFinderTest.jar");
         JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream(jarFile), manifest);
         jarOutputStream.putNextEntry(new ZipEntry("resource"));
         jarOutputStream.write("resource3".getBytes());
         jarOutputStream.putNextEntry(new ZipEntry("jar3"));
         jarOutputStream.write("jar3".getBytes());
         IoUtil.close(jarOutputStream);
+
+        alternateJarFile = new File(targetDir, "alternate.jar");
+        System.out.println(alternateJarFile.getAbsolutePath());
+        jarOutputStream = new JarOutputStream(new FileOutputStream(alternateJarFile), manifest);
+        jarOutputStream.putNextEntry(new ZipEntry("resource"));
+        jarOutputStream.write("resource4".getBytes());
+        jarOutputStream.putNextEntry(new ZipEntry("jar4"));
+        jarOutputStream.write("jar4".getBytes());
+        IoUtil.close(jarOutputStream);
+
+        testResource = new File(targetDir, "testResource");
+        FileOutputStream fileOutputStream = new FileOutputStream(testResource);
+        fileOutputStream.write("testResource".getBytes());
+        IoUtil.close(fileOutputStream);
     }
 
     protected void tearDown() throws Exception {