changeset 1632:7acbff01007f

Netx: Set context classloader for all threads in an application 2009-07-09 Omair Majid <omajid@redhat.com> * rt/net/sourceforge/jnlp/Launcher.java (launchApplication): Call setContextClassLoaderForAllThreads. (setContextClassLoaderForAllThreads): New function.
author Omair Majid <omajid@redhat.com>
date Thu, 09 Jul 2009 17:29:13 -0400
parents 02e02b5a01c0
children 1c9399ade69e
files ChangeLog rt/net/sourceforge/jnlp/Launcher.java
diffstat 2 files changed, 48 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jul 09 17:18:02 2009 -0400
+++ b/ChangeLog	Thu Jul 09 17:29:13 2009 -0400
@@ -1,3 +1,9 @@
+2009-07-09  Omair Majid  <omajid@redhat.com>
+
+	* rt/net/sourceforge/jnlp/Launcher.java
+	(launchApplication): Call setContextClassLoaderForAllThreads.
+	(setContextClassLoaderForAllThreads): New function.
+
 2009-07-09  Omair Majid  <omajid@redhat.com>
 
 	* rt/net/sourceforge/jnlp/cache/ResourceTracker.java:
--- a/rt/net/sourceforge/jnlp/Launcher.java	Thu Jul 09 17:18:02 2009 -0400
+++ b/rt/net/sourceforge/jnlp/Launcher.java	Thu Jul 09 17:29:13 2009 -0400
@@ -23,6 +23,8 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
 import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.LinkedList;
@@ -425,8 +427,7 @@
             Method main = mainClass.getDeclaredMethod("main", new Class[] {String[].class} );
             String args[] = file.getApplication().getArguments();
 
-            // required to make some apps work right
-            Thread.currentThread().setContextClassLoader(app.getClassLoader());
+            setContextClassLoaderForAllThreads(app.getClassLoader());
 
             if (splashScreen != null) {
                 if (splashScreen.isSplashScreenValid()) {
@@ -447,6 +448,45 @@
         }
     }
 
+    /**
+     * Set the classloader as the context classloader for all threads. This is
+     * required to make some applications work. For example, an application that
+     * provides a custom Swing LnF may ask the swing thread to load resources
+     * from their JNLP, which would only work if the Swing thread knows about
+     * the JNLPClassLoader.
+     * 
+     * @param classLoader the classloader to set as the context classloader
+     */
+    private void setContextClassLoaderForAllThreads(ClassLoader classLoader) {
+        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+        ThreadGroup root;
+        
+        root = Thread.currentThread().getThreadGroup();
+        while (root.getParent() != null) {
+            root = root.getParent();
+        }
+
+        /* be prepared for change in thread size */
+        int threadCountGuess = threadBean.getThreadCount();
+        Thread[] threads;
+        do {
+            threadCountGuess = threadCountGuess * 2;
+            threads = new Thread[threadCountGuess];
+            root.enumerate(threads, true);
+        } while (threads[threadCountGuess-1] != null);
+        
+        
+        for (Thread thread: threads) {
+            if (thread != null) {
+                if (JNLPRuntime.isDebug()) {
+                    System.err.println("Setting " + classLoader + " as the classloader for thread " + thread.getName());
+                }
+                thread.setContextClassLoader(classLoader);
+            }
+        }
+        
+    }
+
     /** 
      * Launches a JNLP applet. This method should be called from a
      * thread in the application's thread group.<p>