changeset 1444:85921aeaed32

- Fixed crashes on 64-bit. - Fix freezes on certain sites. - Added support for java_code, java_codebase, etc.
author Deepak Bhole <dbhole@redhat.com>
date Fri, 21 Nov 2008 11:39:51 -0500
parents ff7010bc3cae
children 16d57d401734
files ChangeLog IcedTeaPlugin.cc plugin/icedtea/netscape/javascript/JSObject.java plugin/icedtea/sun/applet/GetWindowPluginCallRequest.java plugin/icedtea/sun/applet/PluginAppletViewer.java plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java rt/net/sourceforge/jnlp/NetxPanel.java
diffstat 7 files changed, 171 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Nov 18 11:04:46 2008 -0500
+++ b/ChangeLog	Fri Nov 21 11:39:51 2008 -0500
@@ -1,3 +1,17 @@
+2008-11-21  Deepak Bhole  <dbhole@redhat.com>
+	* IcedTeaPlugin.cc: Handle memory address->string encoding correctly
+	depending on arch/word size.
+	* plugin/icedtea/netscape/javascript/JSObject.java: Use only long for
+	internal variable, to be on the safe side.
+	* plugin/icedtea/sun/applet/GetWindowPluginCallRequest.java: Ditto.
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Rewrite
+	network->local image cache mapping code to prevent freezes on certain
+	sites. Add support for java_code, java_codebase, etc.
+	* plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java: Fix race
+	condition that froze the vm under the right circumstances.
+	* rt/net/sourceforge/jnlp/NetxPanel.java: Provide function to return the
+	applet classloader.
+
 2008-11-18  Deepak Bhole  <dbhole@redhat.com>
 	* IcedTeaPlugin.cc: Encode newline characters instead of stripping them.
 	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Minor debug
--- a/IcedTeaPlugin.cc	Tue Nov 18 11:04:46 2008 -0500
+++ b/IcedTeaPlugin.cc	Fri Nov 21 11:39:51 2008 -0500
@@ -194,6 +194,7 @@
 	return tv.tv_usec;
 }
 
+
 inline long get_time_in_s()
 {
 	time_t t;
@@ -342,15 +343,12 @@
 #include <queue>
 #include <nsCOMPtr.h>
 #include <nsIThread.h>
+#include <nspr.h>
 
 PRMonitor *jvmMsgQueuePRMonitor;
 std::queue<nsCString> jvmMsgQueue;
 nsCOMPtr<nsIThread> processThread;
 
-#include <nspr.h>
-
-#include <prtypes.h>
-
 // IcedTeaJNIEnv helpers.
 class JNIReference
 {
@@ -700,9 +698,10 @@
 //   printf ("RECEIVE_BOOLEAN: %s result: %x = %s\n",              \
 //           __func__, result, *result ? "true" : "false");
 
-#include <nscore.h>
 #include <nsISupports.h>
 #include <nsIFactory.h>
+#include <nscore.h>
+#include <prtypes.h>
 
 // Factory functions.
 extern "C" NS_EXPORT nsresult NSGetFactory (nsISupports* aServMgr,
@@ -901,7 +900,33 @@
 #include <nsILiveconnect.h>
 #include <nsICollection.h>
 #include <nsIProcess.h>
-#include <map>
+
+#ifndef __STDC_FORMAT_MACROS
+# define __STDC_FORMAT_MACROS
+#endif
+
+#include <inttypes.h>
+
+inline void js_id_to_string(char** str, PLUGIN_JAVASCRIPT_TYPE jsid)
+{
+	if (sizeof(PLUGIN_JAVASCRIPT_TYPE) == 4)
+		sprintf(*str, "%"PRId32, jsid);
+
+	if (sizeof(PLUGIN_JAVASCRIPT_TYPE) == 8)
+		sprintf(*str, "%"PRId64, jsid);
+}
+
+inline PLUGIN_JAVASCRIPT_TYPE string_to_js_id(nsCString str)
+{
+	if (sizeof(PLUGIN_JAVASCRIPT_TYPE) == sizeof(int))
+		return atoi(str.get());
+
+	if (sizeof(PLUGIN_JAVASCRIPT_TYPE) == sizeof(long))
+		return atol(str.get());
+
+	if (sizeof(PLUGIN_JAVASCRIPT_TYPE) == sizeof(long long))
+		return atoll(str.get());
+}
 
 class IcedTeaJNIEnv;
 
@@ -988,7 +1013,7 @@
   PRUint32 next_instance_identifier;
   PRUint32 object_identifier_return;
   PRUint32 instance_count;
-  int javascript_identifier;
+  PLUGIN_JAVASCRIPT_TYPE javascript_identifier;
   int name_identifier;
   int args_identifier;
   int string_identifier;
@@ -1334,7 +1359,6 @@
 #include <nsPIPluginInstancePeer.h>
 #include <nsIPluginInstanceOwner.h>
 #include <nsIRunnable.h>
-#include <iostream>
 
 class IcedTeaRunnable : public nsIRunnable
 {
@@ -2912,8 +2936,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING GetMember\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring nameID = Substring (rest, space + 1);
           name_identifier = nameID.ToInteger (&conversionResult);
           PLUGIN_CHECK ("parse name id", conversionResult);
@@ -2930,8 +2954,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING SetMember\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring nameAndValue = Substring (rest, space + 1);
           space = nameAndValue.FindChar (' ');
           nsDependentCSubstring nameID = Substring (nameAndValue, 0, space);
@@ -2954,8 +2978,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING GetSlot\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring indexStr = Substring (rest, space + 1);
           slot_index = indexStr.ToInteger (&conversionResult);
           PLUGIN_CHECK ("parse name id", conversionResult);
@@ -2972,8 +2996,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING SetSlot\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring nameAndValue = Substring (rest, space + 1);
           space = nameAndValue.FindChar (' ');
           nsDependentCSubstring indexStr = Substring (nameAndValue, 0, space);
@@ -2995,8 +3019,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING Eval\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring stringID = Substring (rest, space + 1);
           string_identifier = stringID.ToInteger (&conversionResult);
           PLUGIN_CHECK ("parse string id", conversionResult);
@@ -3013,8 +3037,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING RemoveMember\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring nameID = Substring (rest, space + 1);
           name_identifier = nameID.ToInteger (&conversionResult);
           PLUGIN_CHECK ("parse name id", conversionResult);
@@ -3031,8 +3055,8 @@
           PLUGIN_DEBUG_0ARG ("POSTING Call\n");
           space = rest.FindChar (' ');
           nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = javascriptID.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) javascriptID);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
           nsDependentCSubstring nameAndArgs = Substring (rest, space + 1);
           space = nameAndArgs.FindChar (' ');
           nsDependentCSubstring nameID = Substring (nameAndArgs, 0, space);
@@ -3052,9 +3076,8 @@
       else if (command == "Finalize")
         {
           PLUGIN_DEBUG_0ARG ("POSTING Finalize\n");
-          nsDependentCSubstring javascriptID = Substring (rest, 0, space);
-          javascript_identifier = rest.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) rest);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
 
           nsCOMPtr<nsIRunnable> event =
             new IcedTeaRunnableMethod<IcedTeaPluginFactory>
@@ -3066,8 +3089,8 @@
       else if (command == "ToString")
         {
           PLUGIN_DEBUG_0ARG ("POSTING ToString\n");
-          javascript_identifier = rest.ToInteger (&conversionResult);
-          PLUGIN_CHECK ("parse javascript id", conversionResult);
+          javascript_identifier = string_to_js_id ((nsCString) rest);
+          PLUGIN_DEBUG_1ARG ("parse javascript id %ld\n", javascript_identifier);
 
           nsCOMPtr<nsIRunnable> event =
             new IcedTeaRunnableMethod<IcedTeaPluginFactory>
@@ -3896,18 +3919,24 @@
                                                NULL, 0, NULL,
                                                &liveconnect_window);
       PLUGIN_CHECK ("get window", result);
-      PLUGIN_DEBUG_1ARG ("HERE 24: %d\n", liveconnect_window);
+      PLUGIN_DEBUG_1ARG ("HERE 24: %ld\n", liveconnect_window);
     }
 
-  PLUGIN_DEBUG_1ARG ("HERE 20: %d\n", liveconnect_window);
+  PLUGIN_DEBUG_1ARG ("HERE 20: %ld\n", liveconnect_window);
+
+  char *windowAddr;
+  windowAddr = (char*) malloc(20*sizeof(char));
+  js_id_to_string(&windowAddr, liveconnect_window);
 
   nsCString message ("context ");
   message.AppendInt (0);
   message += " ";
   message += "JavaScriptGetWindow";
   message += " ";
-  message.AppendInt ((PRUintn) liveconnect_window);
+  message += windowAddr;
   factory->SendMessageToAppletViewer (message);
+
+  free(windowAddr);
 }
 
 IcedTeaPluginInstance::~IcedTeaPluginInstance ()
@@ -4410,7 +4439,6 @@
 #include <nsITransport.h>
 #include <nsNetCID.h>
 #include <nsServiceManagerUtils.h>
-#include <iostream>
 #include <nsIPrincipal.h>
 #include <nsIScriptSecurityManager.h>
 #include <nsIURI.h>
@@ -4628,7 +4656,7 @@
       retstr.AppendInt (value.i);
       break;
     case jlong_type:
-      retstr.AppendInt ((PRUintn) value.j);
+      retstr += IcedTeaPrintfCString ("%ld", value.j);
       break;
     case jfloat_type:
       retstr += IcedTeaPrintfCString ("%f", value.f);
@@ -4757,7 +4785,7 @@
           retstr.AppendInt (args[arg].i);
           break;
         case 'J':
-          retstr.AppendInt ((PRUintn) args[arg].j);
+          retstr += IcedTeaPrintfCString ("%ld", args[arg].j);
           break;
         case 'F':
           retstr += IcedTeaPrintfCString ("%f", args[arg].f);
--- a/plugin/icedtea/netscape/javascript/JSObject.java	Tue Nov 18 11:04:46 2008 -0500
+++ b/plugin/icedtea/netscape/javascript/JSObject.java	Fri Nov 21 11:39:51 2008 -0500
@@ -86,8 +86,7 @@
  */
 public final class JSObject {
     /* the internal object data */
-    private int                               internal;
-    private long                              long_internal;
+    private long                              internal;
 
     /**
      * initialize
@@ -111,7 +110,7 @@
 
     public JSObject(long jsobj_addr) {
         PluginDebug.debug ("JSObject long CONSTRUCTOR");
-        long_internal = jsobj_addr;
+        internal = jsobj_addr;
     }
 
     /**
@@ -231,7 +230,7 @@
     {
         PluginDebug.debug("JSObject.getWindow");
         // FIXME: handle long case as well.
-        int internal = 0;
+        long internal = 0;
         internal = ((PluginAppletViewer)
                     applet.getAppletContext()).getWindow();
         PluginDebug.debug ("GOT IT: " + internal);
--- a/plugin/icedtea/sun/applet/GetWindowPluginCallRequest.java	Tue Nov 18 11:04:46 2008 -0500
+++ b/plugin/icedtea/sun/applet/GetWindowPluginCallRequest.java	Fri Nov 21 11:39:51 2008 -0500
@@ -44,7 +44,7 @@
 
 public class GetWindowPluginCallRequest extends PluginCallRequest {
     // FIXME: look into int vs long JavaScript internal values.
-    int internal;
+    long internal;
 
     public GetWindowPluginCallRequest(String message, String returnString) {
         super(message, returnString);
@@ -55,7 +55,7 @@
         String[] args = message.split(" ");
         // FIXME: add thread ID to messages to support multiple
         // threads using the netscape.javascript package.
-        internal = Integer.parseInt(args[1]);
+        internal = Long.parseLong(args[1]);
         setDone(true);
     }
     
@@ -69,7 +69,7 @@
     	return message.contains("JavaScriptGetWindow");
     }
 
-    public Integer getObject() {
+    public Long getObject() {
     	return this.internal;
     }
 }
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java	Tue Nov 18 11:04:46 2008 -0500
+++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java	Fri Nov 21 11:39:51 2008 -0500
@@ -139,8 +139,6 @@
      
      private double proposedHeightFactor;
      private double proposedWidthFactor;
-     
-     private JNLPClassLoader pluginCL; 
 
      /**
       * Null constructor to allow instantiation via newInstance()
@@ -288,9 +286,6 @@
     	return;
     }
 
-    if (panel instanceof NetxPanel)
-        pluginCL = (JNLPClassLoader) panel.getApplet().getClass().getClassLoader();
-
     PluginDebug.debug("Applet initialized");
 
     // Applet initialized. Find out it's classloader and add it to the list
@@ -607,23 +602,21 @@
          
          try {
 
-             // wait till aplet initializes
-             while (pluginCL == null) {
-                 PluginDebug.debug("Plugin CL is null. Waiting in getCachedImageRef()..");
-             }
+             String originalURL = url.toString();
+             String codeBase = panel.getCodeBase().toString();
 
-             String originalURL = url.toString();
-             String codeBase = pluginCL.getJNLPFile().getCodeBase().toString();
+             if (originalURL.startsWith(codeBase)) {
+
+                 PluginDebug.debug("getCachedImageRef() got URL = " + url);
+                 PluginDebug.debug("getCachedImageRef() plugin codebase = " + codeBase);
 
-             if (originalURL.startsWith("http")) {
-                 PluginDebug.debug("getCachedImageRef() got URL = " + url);
-                 PluginDebug.debug("getCachedImageRef() plugin codebase = " + pluginCL.getJNLPFile().getCodeBase().toString());
+                 // try to fetch it locally
+                 if (panel instanceof NetxPanel) {
+                     URL localURL = null;
+                     localURL = ((NetxPanel) panel).getAppletClassLoader().getResource(originalURL.substring(codeBase.length()));
 
-                 URL localURL = null;
-                 if (originalURL.startsWith(codeBase))
-                     localURL = pluginCL.getResource(originalURL.substring(codeBase.length()));
-
-                 url = localURL != null ? localURL : url;
+                     url = localURL != null ? localURL : url;
+                 }
              }
 
              PluginDebug.debug("getCachedImageRef() getting img from URL = " + url);
@@ -740,7 +733,7 @@
  	}
      }
  
-     public int getWindow() {
+     public long getWindow() {
     	 PluginDebug.debug ("STARTING getWindow");
     	 PluginCallRequest request = requestFactory.getPluginCallRequest("window",
     			 							"instance " + identifier + " " + "GetWindow", 
@@ -753,7 +746,7 @@
     		 PluginDebug.debug ("wait request 1");
     		 synchronized(request) {
     			 PluginDebug.debug ("wait request 2");
-    			 while ((Integer) request.getObject() == 0)
+    			 while ((Long) request.getObject() == 0)
     				 request.wait();
     			 PluginDebug.debug ("wait request 3");
     		 }
@@ -763,11 +756,11 @@
     	 }
 
     	 PluginDebug.debug ("STARTING getWindow DONE");
-    	 return (Integer) request.getObject();
+    	 return (Long) request.getObject();
      }
  
      // FIXME: make private, access via reflection.
-     public static Object getMember(int internal, String name)
+     public static Object getMember(long internal, String name)
      {
     	 AppletSecurityContextManager.getSecurityContext(0).store(name);
          int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
@@ -794,7 +787,7 @@
          return request.getObject();
      }
  
-     public static void setMember(int internal, String name, Object value) {
+     public static void setMember(long internal, String name, Object value) {
     	 AppletSecurityContextManager.getSecurityContext(0).store(name);
          int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
          AppletSecurityContextManager.getSecurityContext(0).store(value);
@@ -823,7 +816,7 @@
      }
  
      // FIXME: handle long index as well.
-     public static void setSlot(int internal, int index, Object value) {
+     public static void setSlot(long internal, int index, Object value) {
     	 AppletSecurityContextManager.getSecurityContext(0).store(value);
          int valueID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(value);
  
@@ -848,7 +841,7 @@
          PluginDebug.debug (" setSlot DONE");
      }
  
-     public static Object getSlot(int internal, int index)
+     public static Object getSlot(long internal, int index)
      {
          // Prefix with dummy instance for convenience.
          PluginCallRequest request = requestFactory.getPluginCallRequest("member", 
@@ -872,7 +865,7 @@
          return request.getObject();
      }
  
-     public static Object eval(int internal, String s)
+     public static Object eval(long internal, String s)
      {
     	 AppletSecurityContextManager.getSecurityContext(0).store(s);
          int stringID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(s);
@@ -899,7 +892,7 @@
          return request.getObject();
      }
  
-     public static void removeMember (int internal, String name) {
+     public static void removeMember (long internal, String name) {
     	 AppletSecurityContextManager.getSecurityContext(0).store(name);
          int nameID = AppletSecurityContextManager.getSecurityContext(0).getIdentifier(name);
  
@@ -924,7 +917,7 @@
          PluginDebug.debug (" RemoveMember DONE");
      }
  
-     public static Object call(int internal, String name, Object args[])
+     public static Object call(long internal, String name, Object args[])
      {
          // FIXME: when is this removed from the object store?
          // FIXME: reference should return the ID.
@@ -956,7 +949,7 @@
          return request.getObject();
      }
  
-     public static void JavaScriptFinalize(int internal)
+     public static void JavaScriptFinalize(long internal)
      {
          // Prefix with dummy instance for convenience.
          PluginCallRequest request = requestFactory.getPluginCallRequest("void",
@@ -979,7 +972,7 @@
          PluginDebug.debug (" finalize DONE");
      }
  
-     public static String javascriptToString(int internal)
+     public static String javascriptToString(long internal)
      {
          // Prefix with dummy instance for convenience.
          PluginCallRequest request = requestFactory.getPluginCallRequest("member",
@@ -1595,6 +1588,28 @@
     						 atts.put("code", ((String) atts.get("classid")).substring(5));
     					 }
 
+                         // java_* aliases override older names:
+                         // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-ie
+                         if (atts.get("java_code") != null) {
+                             atts.put("code", ((String) atts.get("java_code")));
+                         }
+
+                         if (atts.get("java_codebase") != null) {
+                             atts.put("codebase", ((String) atts.get("java_codebase")));
+                         }
+
+                         if (atts.get("java_archive") != null) {
+                             atts.put("archive", ((String) atts.get("java_archive")));
+                         }
+
+                         if (atts.get("java_object") != null) {
+                             atts.put("object", ((String) atts.get("java_object")));
+                         }
+
+                         if (atts.get("java_type") != null) {
+                             atts.put("type", ((String) atts.get("java_type")));
+                         }
+
     					 // The <OBJECT> attribute codebase isn't what
     					 // we want when not dealing with jars. If its 
     					 // defined, remove it in that case.
@@ -1630,6 +1645,28 @@
     						 //skip "java:"
     						 atts.put("code", ((String) atts.get("classid")).substring(5));
     					 }
+    					 
+    					 // java_* aliases override older names:
+    					 // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
+    					 if (atts.get("java_code") != null) {
+    					     atts.put("code", ((String) atts.get("java_code")));
+    					 }
+    					 
+                         if (atts.get("java_codebase") != null) {
+                             atts.put("codebase", ((String) atts.get("java_codebase")));
+                         }
+                         
+                         if (atts.get("java_archive") != null) {
+                             atts.put("archive", ((String) atts.get("java_archive")));
+                         }
+                         
+                         if (atts.get("java_object") != null) {
+                             atts.put("object", ((String) atts.get("java_object")));
+                         }
+    					 
+                         if (atts.get("java_type") != null) {
+                             atts.put("type", ((String) atts.get("java_type")));
+                         }
 
     					 if (atts.get("code") == null && atts.get("object") == null) {
     						 statusMsgStream.println(embedRequiresCodeWarning);
--- a/plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java	Tue Nov 18 11:04:46 2008 -0500
+++ b/plugin/icedtea/sun/applet/PluginMessageHandlerWorker.java	Fri Nov 21 11:39:51 2008 -0500
@@ -24,6 +24,8 @@
 
 			if (message != null) {
 				
+			    PluginDebug.debug("Consumer thread " + id + " consuming " + message);
+			    
 				// ideally, whoever returns things object should mark it 
 				// busy first, but just in case..
 				busy();
@@ -39,21 +41,24 @@
 				}
 
 				this.message = null;
+				
+				PluginDebug.debug("Consumption completed by consumer thread " + id);
+
+	            // mark ourselves free again
+				free();
+				
 			} else {
 				
 				// Sleep when there is nothing to do
-				try {
-					Thread.sleep(Integer.MAX_VALUE);
-					PluginDebug.debug("Consumer thread " + id + " sleeping...");
-				} catch (InterruptedException ie) {
-					PluginDebug.debug("Consumer thread " + id + " woken...");
-					// nothing.. someone woke us up, see if there 
-					// is work to do
-				}
+			    try {
+			        Thread.sleep(Integer.MAX_VALUE);
+			        PluginDebug.debug("Consumer thread " + id + " sleeping...");
+			    } catch (InterruptedException ie) {
+			        PluginDebug.debug("Consumer thread " + id + " woken...");
+			        // nothing.. someone woke us up, see if there 
+			        // is work to do
+			    }
 			}
-			
-			// mark ourselves free again
-			free();
 		}
 	}
 	
--- a/rt/net/sourceforge/jnlp/NetxPanel.java	Tue Nov 18 11:04:46 2008 -0500
+++ b/rt/net/sourceforge/jnlp/NetxPanel.java	Fri Nov 21 11:39:51 2008 -0500
@@ -40,6 +40,7 @@
 {
     private PluginBridge bridge = null;
     private boolean exitOnFailure = true;
+    private AppletInstance appInst = null;
 
     public NetxPanel(URL documentURL, Hashtable atts)
     {
@@ -81,7 +82,7 @@
     		status = APPLET_LOAD;
 
     		Launcher l = new Launcher(exitOnFailure);
-    		AppletInstance appInst = null;
+    		
                 try {
                     appInst = (AppletInstance) l.launch(bridge, this);
                 } catch (LaunchException e) {
@@ -128,5 +129,9 @@
     	this.atts.put("height", Integer.toString(height));
     	this.atts.put("width", Integer.toString(width));
     }
+    
+    public ClassLoader getAppletClassLoader() {
+        return appInst.getClassLoader();
+    }
 }