changeset 452:924a83097ed7

Fix problem in resolving classes The bug manifests when the following sequence of steps happen: 1. An applet with both a codebase and a jar (archive) is loaded 2. A class Foo is loaded using the codebase classloader 3. The Foo class tries to load a class Bar that is specified in the jar archive. The Bar class is not found. The following applet reproduces the problem: http://javadjvu.foxtrottechnologies.com/cgi-bin/djvuapplet.pl/examples/deer.djvu?zoom=page The fix addresses the problem by ensuring that the codebase classloader asks the classloader that knows about the jar archive to resolve classes too.
author Omair Majid <omajid@redhat.com>
date Thu, 28 Jun 2012 14:53:07 -0400
parents c372fa282f61
children 8f7e65f53eb6
files ChangeLog netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java tests/netx/unit/net/sourceforge/jnlp/runtime/CodeBaseClassLoaderTest.java
diffstat 3 files changed, 71 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jun 28 17:48:34 2012 +0200
+++ b/ChangeLog	Thu Jun 28 14:53:07 2012 -0400
@@ -1,3 +1,13 @@
+2012-06-28  Omair Majid  <omajid@redhat.com>
+
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+	(findClass): Invoke CodeBaseClassLoader.findClass with a flag to avoid
+	infinite recursion.
+	(CodeBaseClassLoader.findClass(String)): Delegate to ...
+	(CodeBaseClassLoader.findClass(String,boolean)): New method.
+	* tests/netx/unit/net/sourceforge/jnlp/runtime/CodeBaseClassLoaderTest.java
+	(testParentClassLoaderIsAskedForClasses): New method.
+
 2012-06-28 Jiri Vanek <jvanek@redhat.com>
 
 	Correctly backup all log files re-writable by emma during code-coverage
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Thu Jun 28 17:48:34 2012 +0200
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Thu Jun 28 14:53:07 2012 -0400
@@ -1577,8 +1577,8 @@
 
         // Try codebase loader
         if (codeBaseLoader != null)
-            return codeBaseLoader.findClass(name);
-        
+            return codeBaseLoader.findClass(name, true);
+
         // All else failed. Throw CNFE
         throw new ClassNotFoundException(name);
     }
@@ -2060,6 +2060,18 @@
 
         @Override
         public Class<?> findClass(String name) throws ClassNotFoundException {
+            return findClass(name, false);
+        }
+
+        public Class<?> findClass(String name, boolean recursivelyInvoked) throws ClassNotFoundException {
+
+            if (!recursivelyInvoked) {
+                try {
+                    return parentJNLPClassLoader.findClass(name);
+                } catch (ClassNotFoundException cnfe) {
+                    // continue
+                }
+            }
 
             // If we have searched this path before, don't try again
             if (Arrays.equals(super.getURLs(), notFoundResources.get(name)))
--- a/tests/netx/unit/net/sourceforge/jnlp/runtime/CodeBaseClassLoaderTest.java	Thu Jun 28 17:48:34 2012 +0200
+++ b/tests/netx/unit/net/sourceforge/jnlp/runtime/CodeBaseClassLoaderTest.java	Thu Jun 28 14:53:07 2012 -0400
@@ -37,9 +37,11 @@
 
 package net.sourceforge.jnlp.runtime;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Locale;
 
@@ -55,9 +57,11 @@
 
 import org.junit.Test;
 
-@Bug(id={"PR895","http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017626.html","http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017667.html"})
 public class CodeBaseClassLoaderTest {
 
+    @Bug(id={"PR895",
+            "http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017626.html",
+            "http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017667.html"})
     @Test
     public void testResourceLoadSuccessCaching() throws LaunchException, ClassNotFoundException, IOException, ParseException {
         final URL JAR_URL = new URL("http://icedtea.classpath.org/netx/about.jar");
@@ -100,6 +104,9 @@
         assertTrue(timeOnSecondTry < (timeOnFirstTry / 10));
     }
 
+    @Bug(id={"PR895",
+            "http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017626.html",
+            "http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2012-March/017667.html"})
     @Test
     public void testResourceLoadFailureCaching() throws LaunchException, ClassNotFoundException, IOException, ParseException {
         final URL JAR_URL = new URL("http://icedtea.classpath.org/netx/about.jar");
@@ -142,4 +149,43 @@
         assertTrue(timeOnSecondTry < (timeOnFirstTry / 10));
     }
 
+    @Test
+    public void testParentClassLoaderIsAskedForClasses() throws MalformedURLException, LaunchException {
+        final URL JAR_URL = new URL("http://icedtea.classpath.org/netx/about.jar");
+        final URL CODEBASE_URL = new URL("http://icedtea.classpath.org/netx/");
+
+        JNLPFile dummyJnlpFile = new JNLPFile() {
+            @Override
+            public ResourcesDesc getResources() {
+                return new ResourcesDesc(null, new Locale[0], new String[0], new String[0]);
+            }
+
+            @Override
+            public URL getCodeBase() {
+                return CODEBASE_URL;
+            }
+
+            @Override
+            public SecurityDesc getSecurity() {
+                return new SecurityDesc(null, SecurityDesc.SANDBOX_PERMISSIONS, null);
+            }
+        };
+
+        final boolean[] parentWasInvoked = new boolean[1];
+
+        JNLPClassLoader parent = new JNLPClassLoader(dummyJnlpFile, null) {
+            @Override
+            protected Class<?> findClass(String name) throws ClassNotFoundException {
+                parentWasInvoked[0] = true;
+                throw new ClassNotFoundException(name);
+            }
+        };
+        CodeBaseClassLoader classLoader = new CodeBaseClassLoader(new URL[] { JAR_URL, CODEBASE_URL }, parent);
+        try {
+            classLoader.findClass("foo");
+            assertFalse("should not happen", true);
+        } catch (ClassNotFoundException cnfe) { /* ignore */ }
+
+        assertTrue(parentWasInvoked[0]);
+    }
 }