/hg/icedtea-web: - PR475, RH604061: Allow applets from the same ...

dbhole at icedtea.classpath.org dbhole at icedtea.classpath.org
Fri Mar 4 14:31:39 PST 2011


changeset 5e62b3580dcc in /hg/icedtea-web
details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=5e62b3580dcc
author: Deepak Bhole <dbhole at redhat.com>
date: Fri Mar 04 17:34:32 2011 -0500

	- PR475, RH604061: Allow applets from the same page to use the same
	classloader


diffstat:

5 files changed, 23 insertions(+), 6 deletions(-)
ChangeLog                                                  |   15 ++++++++++++
netx/net/sourceforge/jnlp/PluginBridge.java                |    3 --
netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java     |    1 
netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java |    6 +++-
plugin/icedteanp/java/sun/applet/PluginAppletViewer.java   |    4 ++-

diffs (309 lines):

diff -r 64b9d3a8239c -r 5e62b3580dcc ChangeLog
--- a/ChangeLog	Thu Mar 03 17:56:00 2011 -0500
+++ b/ChangeLog	Fri Mar 04 17:34:32 2011 -0500
@@ -1,3 +1,31 @@ 2011-03-03  Deepak Bhole <dbhole at redhat.
+2011-03-04  Deepak Bhole <dbhole at redhat.com>
+
+	* NEWS: Updated.
+	* netx/net/sourceforge/jnlp/PluginBridge.java (PluginBridge): Use
+	documentbase as a uniquekey so that the classloader may be shared by
+	applets from the same page.
+	* netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Added new
+	CodeBaseClassLoader class to load codebase (from path instead of a file)
+	classes.
+	(getInstance): Try to match file locations only for Web Start apps. For
+	plugin, merge the new loader into current one.
+	(enableCodeBase): Use the new addToCodeBaseLoader method.
+	(findLoadedClassAll): Search the codebase loader if the class was not
+	found in the file loaders.
+	(findClass): Likewise.
+	(getResource): Likewise.
+	(findResources): Likewise.
+	(merge): Merge codebase loaders.
+	(addToCodeBaseLoader): New method. Adds a given url to the codebase loader
+	if it is a path.
+	(CodeBaseClassLoader): New inner class. Extends URLClassLoader to expose
+	its protected methods like addURL.
+	* netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(getApplication): Accomodate the fact that the classloader for a class may
+	be a CodeBaseClassLoader.
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (run):
+	Likewise.
+
 2011-03-03  Deepak Bhole <dbhole at redhat.com>
 
 	* plugin/icedteanp/IcedTeaNPPlugin.cc
diff -r 64b9d3a8239c -r 5e62b3580dcc NEWS
--- a/NEWS	Thu Mar 03 17:56:00 2011 -0500
+++ b/NEWS	Fri Mar 04 17:34:32 2011 -0500
@@ -21,6 +21,7 @@ New in release 1.1 (2011-XX-XX):
   - Use Firefox's proxy settings if possible
   - RH669942: javaws fails to download version/packed files (missing support for jnlp.packEnabled and jnlp.versionEnabled)
 * Plugin
+  - PR475, RH604061: Allow applets from the same page to use the same classloader
   - PR612: NetDania application ends on java.security.AccessControlException: access denied (java.util.PropertyPermission browser read)
 
 New in release 1.0 (2010-XX-XX):
diff -r 64b9d3a8239c -r 5e62b3580dcc netx/net/sourceforge/jnlp/PluginBridge.java
--- a/netx/net/sourceforge/jnlp/PluginBridge.java	Thu Mar 03 17:56:00 2011 -0500
+++ b/netx/net/sourceforge/jnlp/PluginBridge.java	Fri Mar 04 17:34:32 2011 -0500
@@ -130,9 +130,10 @@ public class PluginBridge extends JNLPFi
         else
             security = null;
 
-        this.uniqueKey = Calendar.getInstance().getTimeInMillis() + "-" +
-                         Math.abs(((new java.util.Random()).nextInt())) + "-" +
-                         documentBase;
+        // Plugin needs to share classloaders so that applet instances from 
+        // same page can communicate (there are applets known to require 
+        // such communication for proper functionality)
+        this.uniqueKey = documentBase.toString();
     }
 
     public String getTitle() {
diff -r 64b9d3a8239c -r 5e62b3580dcc netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Thu Mar 03 17:56:00 2011 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Fri Mar 04 17:34:32 2011 -0500
@@ -145,6 +145,9 @@ public class JNLPClassLoader extends URL
     /** Map of specific codesources to securitydesc */
     private HashMap<URL, SecurityDesc> jarLocationSecurityMap =
             new HashMap<URL, SecurityDesc>();
+    
+    /** Loader for codebase (which is a path, rather than a file) */
+    private CodeBaseClassLoader codeBaseLoader;
 
     /**
      * Create a new JNLPClassLoader from the specified file.
@@ -276,10 +279,12 @@ public class JNLPClassLoader extends URL
 
         try {
 
-            // If base loader is null, or the baseloader's file and this
-            // file is different, initialize a new loader
+
+            // A null baseloader implies that no loader has been created 
+            // for this codebase/jnlp yet. Create one.
             if (baseLoader == null ||
-                        !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation())) {
+                    (file.isApplication() && 
+                     !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) {
 
                 loader = new JNLPClassLoader(file, policy);
 
@@ -303,6 +308,13 @@ public class JNLPClassLoader extends URL
 
             } else {
                 // if key is same and locations match, this is the loader we want
+                if (!file.isApplication()) {
+                    // If this is an applet, we do need to consider its loader
+                    loader = new JNLPClassLoader(file, policy);
+
+                    if (baseLoader != null)
+                        baseLoader.merge(loader);
+                }
                 loader = baseLoader;
             }
 
@@ -529,7 +541,7 @@ public class JNLPClassLoader extends URL
      * loaded from the codebase are not cached.
      */
     public void enableCodeBase() {
-        addURL(file.getCodeBase()); // nothing happens if called more that once?
+        addToCodeBaseLoader(file.getCodeBase());
     }
 
     /**
@@ -958,8 +970,13 @@ public class JNLPClassLoader extends URL
             if (result != null)
                 return result;
         }
-
-        return null;
+        
+        // Result is still null. Return what the codebaseloader 
+        // has (which returns null if it is not loaded there either)
+        if (codeBaseLoader != null)
+            return codeBaseLoader.findLoadedClassFromParent(name);
+        else
+            return null;
     }
 
     /**
@@ -1067,6 +1084,11 @@ public class JNLPClassLoader extends URL
             }
         }
 
+        // Try codebase loader
+        if (codeBaseLoader != null)
+            return codeBaseLoader.findClass(name);
+        
+        // All else failed. Throw CNFE
         throw new ClassNotFoundException(name);
     }
 
@@ -1109,6 +1131,10 @@ public class JNLPClassLoader extends URL
         for (int i = 1; i < loaders.length; i++)
             if (result == null)
                 result = loaders[i].getResource(name);
+        
+        // If result is still null, look in the codebase loader
+        if (result == null && codeBaseLoader != null)
+            result = codeBaseLoader.getResource(name);
 
         return result;
     }
@@ -1120,15 +1146,23 @@ public class JNLPClassLoader extends URL
     @Override
     public Enumeration<URL> findResources(String name) throws IOException {
         Vector<URL> resources = new Vector<URL>();
+        Enumeration<URL> e;
 
         for (int i = 0; i < loaders.length; i++) {
-            Enumeration<URL> e;
 
             if (loaders[i] == this)
                 e = super.findResources(name);
             else
                 e = loaders[i].findResources(name);
 
+            while (e.hasMoreElements())
+                resources.add(e.nextElement());
+        }
+
+        // Add resources from codebase (only if nothing was found above, 
+        // otherwise the server will get hammered) 
+        if (resources.isEmpty() && codeBaseLoader != null) {
+            e = codeBaseLoader.findResources(name);
             while (e.hasMoreElements())
                 resources.add(e.nextElement());
         }
@@ -1250,6 +1284,9 @@ public class JNLPClassLoader extends URL
         // jars
         for (URL u : extLoader.getURLs())
             addURL(u);
+        
+        // Codebase
+        addToCodeBaseLoader(extLoader.file.getCodeBase());
 
         // native search paths
         for (File nativeDirectory : extLoader.getNativeDirectories())
@@ -1258,6 +1295,28 @@ public class JNLPClassLoader extends URL
         // security descriptors
         for (URL key : extLoader.jarLocationSecurityMap.keySet()) {
             jarLocationSecurityMap.put(key, extLoader.jarLocationSecurityMap.get(key));
+        }
+    }
+
+    /**
+     * Adds the given path to the path loader
+     * 
+     * @param URL the path to add
+     * @throws IllegalArgumentException If the given url is not a path
+     */
+    private void addToCodeBaseLoader(URL u) {
+
+        // Only paths may be added
+        if (!u.getFile().endsWith("/")) {
+            throw new IllegalArgumentException("addToPathLoader only accepts path based URLs");
+        }
+
+        // If there is no loader yet, create one, else add it to the 
+        // existing one (happens when called from merge())
+        if (codeBaseLoader == null) {
+            codeBaseLoader = new CodeBaseClassLoader(new URL[] { u }, this);
+        } else {
+            codeBaseLoader.addURL(u);
         }
     }
 
@@ -1283,4 +1342,49 @@ public class JNLPClassLoader extends URL
         return new DownloadOptions(usePack, useVersion);
     }
 
+    /*
+     * Helper class to expose protected URLClassLoader methods.
+     */
+
+    public class CodeBaseClassLoader extends URLClassLoader {
+
+        JNLPClassLoader parentJNLPClassLoader;
+        
+        public CodeBaseClassLoader(URL[] urls, JNLPClassLoader cl) {
+            super(urls);
+            parentJNLPClassLoader = cl;
+        }
+
+        @Override
+        public void addURL(URL url) { 
+            super.addURL(url); 
+        }
+
+        @Override
+        public Class<?> findClass(String name) throws ClassNotFoundException { 
+            return super.findClass(name); 
+        }
+
+        /**
+         * Returns the output of super.findLoadedClass().
+         * 
+         * The method is renamed because ClassLoader.findLoadedClass() is final
+         * 
+         * @param name The name of the class to find
+         * @return Output of ClassLoader.findLoadedClass() which is the class if found, null otherwise 
+         * @see java.lang.ClassLoader#findLoadedClass(String)
+         */
+        public Class<?> findLoadedClassFromParent(String name) {
+            return findLoadedClass(name);
+        }
+
+        /**
+         * Returns JNLPClassLoader that encompasses this loader
+         * 
+         * @return parent JNLPClassLoader
+         */
+        public JNLPClassLoader getParentJNLPClassLoader() {
+            return parentJNLPClassLoader;
+        }
+    }
 }
diff -r 64b9d3a8239c -r 5e62b3580dcc netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
--- a/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Thu Mar 03 17:56:00 2011 -0500
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Fri Mar 04 17:34:32 2011 -0500
@@ -199,8 +199,16 @@ class JNLPSecurityManager extends AWTSec
 
         // this needs to be tightened up
         for (int i = 0; i < stack.length && i < maxDepth; i++) {
-            if (stack[i].getClassLoader() instanceof JNLPClassLoader) {
-                JNLPClassLoader loader = (JNLPClassLoader) stack[i].getClassLoader();
+            ClassLoader cl = stack[i].getClassLoader();
+            
+            // Since we want to deal with JNLPClassLoader, extract it if this 
+            // is a codebase loader
+            if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+                cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+            if (cl instanceof JNLPClassLoader) {
+
+                JNLPClassLoader loader = (JNLPClassLoader) cl;
 
                 if (loader != null && loader.getApplication() != null) {
                     return loader.getApplication();
diff -r 64b9d3a8239c -r 5e62b3580dcc plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Thu Mar 03 17:56:00 2011 -0500
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Fri Mar 04 17:34:32 2011 -0500
@@ -1646,7 +1646,14 @@ public class PluginAppletViewer extends 
          {
              public void run()
              {
-                 ThreadGroup tg = ((JNLPClassLoader) p.applet.getClass().getClassLoader()).getApplication().getThreadGroup();
+                 ClassLoader cl = p.applet.getClass().getClassLoader();
+                 
+                 // Since we want to deal with JNLPClassLoader, extract it if this 
+                 // is a codebase loader
+                 if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+                     cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+                 ThreadGroup tg = ((JNLPClassLoader) cl).getApplication().getThreadGroup();
 
                  appletShutdown(p);
                  appletPanels.removeElement(p);



More information about the distro-pkg-dev mailing list