changeset 1033:4c642bbb2285

- Added support for multiple simultaneous applet load (same tab or different) - http://www.w3.org/People/mimasa/test/object/java/clock - Added support for load via object/embed/applet tags with "classid" - i.e. everything here http://www.w3.org/People/mimasa/test/object/java/ - Improved shutdown subroutine for clean (er) exit - Added support for applets that specify height/width as %'s of window size - Fixed a couple of minor race condition issues
author Deepak Bhole <dbhole@redhat.com>
date Fri, 05 Sep 2008 12:11:57 -0400
parents 2cfd464ee271
children aacc3e8a8e16
files ChangeLog IcedTeaPlugin.cc patches/icedtea-liveconnect.patch patches/icedtea-webstart.patch rt/net/sourceforge/jnlp/NetxPanel.java rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java
diffstat 6 files changed, 576 insertions(+), 264 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Sep 01 10:36:56 2008 +0200
+++ b/ChangeLog	Fri Sep 05 12:11:57 2008 -0400
@@ -1,3 +1,15 @@
+2008-08-26  Deepak Bhole  <dbhole@redhat.com>
+
+	* IcedTeaPlugin.cc: Support for multiple simultaneous applet load.
+	* patches/icedtea-liveconnect.patch: Support for multiple simultaneous
+	applet load. Improved shutdown.
+	* patches/icedtea-webstart.patch: Added support for applets that specify
+	height/width as factor of window size.
+	* rt/net/sourceforge/jnlp/NetxPanel.java: Added synchronization for
+	JNLPRuntime initialization.
+	* rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Added mutex object
+	around which initialization can be synchronized.
+
 2008-08-28  Mark Wielaard  <mjw@redhat.com>
 
 	* patches/icedtea-clean-crypto.patch: New patch.
--- a/IcedTeaPlugin.cc	Mon Sep 01 10:36:56 2008 +0200
+++ b/IcedTeaPlugin.cc	Fri Sep 05 12:11:57 2008 -0400
@@ -246,6 +246,11 @@
 static char* appletviewer_executable = NULL;
 static char* libjvm_so = NULL;
 
+class IcedTeaPluginFactory;
+
+static PRBool factory_created = PR_FALSE;
+static IcedTeaPluginFactory* factory = NULL;
+
 #include <nspr.h>
 
 #include <prtypes.h>
@@ -375,6 +380,26 @@
 #define MESSAGE_SEND()                          \
   factory->SendMessageToAppletViewer (message);
 
+// FIXME: Right now, the macro below will exit only 
+// if error occured and we are in the middle of a 
+// shutdown (so that the permanent loop does not block 
+// proper exit). We need better error handling
+
+#define PROCESS_PENDING_EVENTS_REF(reference) \
+    if (factory->shutting_down == PR_TRUE && \
+		factory->resultMap[reference]->errorOccured == PR_TRUE) \
+	{                                                           \
+		printf("Error occured. Exiting function\n");            \
+		return NS_ERROR_FAILURE; \
+	} \
+	PRBool hasPending;  \
+	factory->current->HasPendingEvents(&hasPending); \
+	if (hasPending == PR_TRUE) { \
+		PRBool processed = PR_FALSE; \
+		factory->current->ProcessNextEvent(PR_TRUE, &processed); \
+	} else { \
+		PR_Sleep(PR_INTERVAL_NO_WAIT); \
+	}
 
 #define PROCESS_PENDING_EVENTS \
 	PRBool hasPending;  \
@@ -391,7 +416,7 @@
   printf ("RECEIVE 1\n");                                               \
   while (factory->resultMap[reference]->returnIdentifier == -1)     \
     {                                                                   \
-      PROCESS_PENDING_EVENTS;                                           \
+      PROCESS_PENDING_EVENTS_REF (reference);                                \
     }                                                                   \
   printf ("RECEIVE 3\n"); \
   if (factory->resultMap[reference]->returnIdentifier == 0) \
@@ -412,7 +437,7 @@
   printf("RECEIVE ID 1\n");                                             \
   while (factory->resultMap[reference]->returnIdentifier == -1)     \
     {                                                                   \
-      PROCESS_PENDING_EVENTS;                                           \
+      PROCESS_PENDING_EVENTS_REF (reference);                                \
     }                                                                   \
                                                                         \
   *id = reinterpret_cast<cast>                                  \
@@ -426,7 +451,7 @@
   printf("RECEIVE VALUE 1\n");                                             \
   while (factory->resultMap[reference]->returnValue == "")            \
     {                                                                      \
-      PROCESS_PENDING_EVENTS;                                              \
+      PROCESS_PENDING_EVENTS_REF (reference);                                   \
     }                                                                      \
   *result = ParseValue (type, factory->resultMap[reference]->returnValue);            
 // \
@@ -442,7 +467,7 @@
   printf("RECEIVE SIZE 1\n");                                 \
   while (factory->resultMap[reference]->returnValue == "")                        \
     {                                                           \
-      PROCESS_PENDING_EVENTS;                                                      \
+      PROCESS_PENDING_EVENTS_REF (reference);                        \
     }                                                           \
   nsresult conversionResult;                                    \
   *result = factory->resultMap[reference]->returnValue.ToInteger (&conversionResult); \
@@ -458,7 +483,7 @@
   printf("RECEIVE STRING 1\n");                                 \
   while (factory->resultMap[reference]->returnValue == "")                            \
     {                                                           \
-      PROCESS_PENDING_EVENTS;                                                      \
+      PROCESS_PENDING_EVENTS_REF (reference);                        \
     }                                                           \
 	printf("Setting result to: %s\n", strdup (factory->resultMap[reference]->returnValue.get ())); \
   *result = reinterpret_cast<char_type const*>                  \
@@ -474,7 +499,7 @@
   printf("RECEIVE STRING UCS 1\n");                                 \
   while (factory->resultMap[reference]->returnValueUCS.IsEmpty())                        \
     {                                                           \
-      PROCESS_PENDING_EVENTS;                                                      \
+      PROCESS_PENDING_EVENTS_REF (reference);                        \
     }                                                           \
   int length = factory->resultMap[reference]->returnValueUCS.Length ();               \
   jchar* newstring = static_cast<jchar*> (PR_Malloc (length));  \
@@ -493,7 +518,7 @@
   printf("RECEIVE BOOLEAN 1\n");                             \
   while (factory->resultMap[reference]->returnIdentifier == -1)               \
     {                                                           \
-      PROCESS_PENDING_EVENTS;                                                      \
+      PROCESS_PENDING_EVENTS_REF (reference);                        \
     }                                                           \
   *result = factory->resultMap[reference]->returnIdentifier;
 //      res = factory->current->ProcessNextEvent (PR_TRUE,        \
@@ -651,6 +676,7 @@
   		PRUint32 returnIdentifier;
 		nsCString returnValue;
 		nsString returnValueUCS;
+		PRBool errorOccured;
 
 };
 
@@ -661,6 +687,7 @@
 	returnIdentifier = -1;
 	returnValue.Truncate();
 	returnValueUCS.Truncate();
+	errorOccured = PR_FALSE;
 }
 
 ResultContainer::~ResultContainer ()
@@ -680,6 +707,7 @@
 	returnIdentifier = -1;
 	returnValue.Truncate();
 	returnValueUCS.Truncate();
+	errorOccured = PR_FALSE;
 }
 
 #include <nsTArray.h>
@@ -732,7 +760,10 @@
   PRBool IsConnected ();
   nsCOMPtr<nsIAsyncInputStream> async;
   nsCOMPtr<nsIThread> current;
+  nsCOMPtr<nsIInputStream> input;
+  nsCOMPtr<nsIOutputStream> output;
   ReferenceHashtable references;
+  PRBool shutting_down;
   // FIXME: make private?
   JNIEnv* proxyEnv;
   nsISecureEnv* secureEnv;
@@ -755,11 +786,10 @@
   nsresult StartAppletviewer ();
   void ProcessMessage();
   void ConsumeMsgFromJVM();
+  void CreateSocket();
   nsCOMPtr<nsIThread> processThread;
   nsCOMPtr<IcedTeaEventSink> sink;
   nsCOMPtr<nsISocketTransport> transport;
-  nsCOMPtr<nsIInputStream> input;
-  nsCOMPtr<nsIOutputStream> output;
   nsCOMPtr<nsIProcess> applet_viewer_process;
   PRBool connected;
   PRUint32 next_instance_identifier;
@@ -774,7 +804,6 @@
   int string_identifier;
   int slot_index;
   int value_identifier;
-  PRBool shutting_down;
 
 /**
  * JNI I/O related code
@@ -1113,6 +1142,77 @@
   int contextCounter;
 };
 
+
+#include <nsIServerSocket.h>
+#include <nsNetError.h>
+#include <nsPIPluginInstancePeer.h>
+#include <nsIPluginInstanceOwner.h>
+#include <nsIRunnable.h>
+#include <iostream>
+
+class IcedTeaRunnable : public nsIRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+
+  IcedTeaRunnable ();
+
+  ~IcedTeaRunnable ();
+};
+
+NS_IMPL_ISUPPORTS1 (IcedTeaRunnable, nsIRunnable)
+
+IcedTeaRunnable::IcedTeaRunnable ()
+{
+}
+
+IcedTeaRunnable::~IcedTeaRunnable ()
+{
+}
+
+NS_IMETHODIMP
+IcedTeaRunnable::Run ()
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+template <class T>
+class IcedTeaRunnableMethod : public IcedTeaRunnable
+{
+public:
+  typedef void (T::*Method) ();
+
+  IcedTeaRunnableMethod (T* object, Method method);
+  NS_IMETHOD Run ();
+
+  ~IcedTeaRunnableMethod ();
+
+  T* object;
+  Method method;
+};
+
+template <class T>
+IcedTeaRunnableMethod<T>::IcedTeaRunnableMethod (T* object, Method method)
+: object (object),
+  method (method)
+{
+  NS_ADDREF (object);
+}
+
+template <class T>
+IcedTeaRunnableMethod<T>::~IcedTeaRunnableMethod ()
+{
+  NS_RELEASE (object);
+}
+
+template <class T> NS_IMETHODIMP
+IcedTeaRunnableMethod<T>::Run ()
+{
+  (object->*method) ();
+  return NS_OK;
+}
+
 NS_IMPL_ISUPPORTS6 (IcedTeaPluginFactory, nsIFactory, nsIPlugin, nsIJVMManager,
                     nsIJVMPrefsWindow, nsIJVMPlugin, nsIInputStreamCallback)
 
@@ -1141,6 +1241,8 @@
   // FIXME: why did this crash with threadManager == 0x0 on shutdown?
   PLUGIN_TRACE_FACTORY ();
   secureEnv = 0;
+  factory_created = PR_FALSE;
+  factory = NULL;
   printf ("DECONSTRUCTING FACTORY\n");
 }
 
@@ -1189,38 +1291,8 @@
 
   PLUGIN_DEBUG_TWO ("Factory::Initialize: using", appletviewer_executable);
 
-  // Start appletviewer process for this plugin instance.
   nsCOMPtr<nsIComponentManager> manager;
   result = NS_GetComponentManager (getter_AddRefs (manager));
-  PLUGIN_CHECK_RETURN ("get component manager", result);
-
-  result = manager->CreateInstance
-    (nsILiveconnect::GetCID (),
-     nsnull, NS_GET_IID (nsILiveconnect),
-     getter_AddRefs (liveconnect));
-  PLUGIN_CHECK_RETURN ("liveconnect", result);
-
-/*
- * Socket initialization code for TCP/IP communication
- *
- */
- 
-  nsCOMPtr<nsIServerSocket> socket;
-  result = manager->CreateInstanceByContractID (NS_SERVERSOCKET_CONTRACTID,
-                                                nsnull,
-                                                NS_GET_IID (nsIServerSocket),
-                                                getter_AddRefs (socket));
-  PLUGIN_CHECK_RETURN ("create server socket", result);
-
-  // FIXME: hard-coded port
-  result = socket->Init (50007, PR_TRUE, -1);
-
-
-  PLUGIN_CHECK_RETURN ("socket init", result);
-
-  nsCOMPtr<IcedTeaSocketListener> listener = new IcedTeaSocketListener (this);
-  result = socket->AsyncListen (listener);
-  PLUGIN_CHECK_RETURN ("add socket listener", result);
 
 /**
  * JNI I/O code
@@ -1230,9 +1302,6 @@
 */
   jvmMsgQueuePRMonitor = PR_NewMonitor();
 
-  result = StartAppletviewer ();
-  PLUGIN_CHECK_RETURN ("started appletviewer", result);
-
   nsCOMPtr<nsIThreadManager> threadManager;
   result = manager->CreateInstanceByContractID
     (NS_THREADMANAGER_CONTRACTID, nsnull, NS_GET_IID (nsIThreadManager),
@@ -1248,37 +1317,91 @@
  *
  */
  
+  nsCOMPtr<nsIThread> socketCreationThread;
+  nsCOMPtr<nsIRunnable> socketCreationEvent =
+							new IcedTeaRunnableMethod<IcedTeaPluginFactory>
+							(this, &IcedTeaPluginFactory::IcedTeaPluginFactory::CreateSocket);
+
+  NS_NewThread(getter_AddRefs(socketCreationThread), socketCreationEvent);
+
   PLUGIN_DEBUG ("Instance::Initialize: awaiting connection from appletviewer");
   PRBool processed;
+
   // FIXME: move this somewhere applet-window specific so it doesn't block page
   // display.
   // FIXME: this doesn't work with thisiscool.com.
   while (!IsConnected ())
     {
-      result = current->ProcessNextEvent (PR_TRUE, &processed);
-      PLUGIN_CHECK_RETURN ("wait for connection: process next event", result);
+//      result = socketCreationThread->ProcessNextEvent (PR_TRUE, &processed);
+//      PLUGIN_CHECK_RETURN ("wait for connection: process next event", result);
     }
   PLUGIN_DEBUG ("Instance::Initialize:"
                 " got confirmation that appletviewer is running.");
 
-  result = transport->OpenOutputStream (nsITransport::OPEN_BLOCKING,
-                                        nsnull, nsnull,
-                                        getter_AddRefs (output));
-  PLUGIN_CHECK_RETURN ("output stream", result);
-
-  result = transport->OpenInputStream (0, nsnull, nsnull,
-                                       getter_AddRefs (input));
-  PLUGIN_CHECK_RETURN ("input stream", result);
-
-  async = do_QueryInterface (input, &result);
-  PLUGIN_CHECK_RETURN ("async input stream", result);
-
-  result = async->AsyncWait (this, 0, 0, current);
-  PLUGIN_CHECK_RETURN ("add async wait", result);
-
   return NS_OK;
 }
 
+void
+IcedTeaPluginFactory::CreateSocket ()
+{
+
+  PRBool processed;
+  nsresult result;
+
+  // Start appletviewer process for this plugin instance.
+  nsCOMPtr<nsIComponentManager> manager;
+  result = NS_GetComponentManager (getter_AddRefs (manager));
+  PLUGIN_CHECK ("get component manager", result);
+
+  result = manager->CreateInstance
+    (nsILiveconnect::GetCID (),
+     nsnull, NS_GET_IID (nsILiveconnect),
+     getter_AddRefs (liveconnect));
+  PLUGIN_CHECK ("liveconnect", result);
+
+  nsCOMPtr<nsIThreadManager> threadManager;
+  nsCOMPtr<nsIThread> curr_thread;
+  result = manager->CreateInstanceByContractID
+    (NS_THREADMANAGER_CONTRACTID, nsnull, NS_GET_IID (nsIThreadManager),
+     getter_AddRefs (threadManager));
+  PLUGIN_CHECK ("thread manager", result);
+
+  result = threadManager->GetCurrentThread (getter_AddRefs (curr_thread));
+
+
+/*
+ * Socket initialization code for TCP/IP communication
+ *
+ */
+ 
+  nsCOMPtr<nsIServerSocket> socket;
+  result = manager->CreateInstanceByContractID (NS_SERVERSOCKET_CONTRACTID,
+                                                nsnull,
+                                                NS_GET_IID (nsIServerSocket),
+                                                getter_AddRefs (socket));
+  PLUGIN_CHECK ("create server socket", result);
+
+  // FIXME: hard-coded port
+  result = socket->Init (50007, PR_TRUE, -1);
+
+
+  PLUGIN_CHECK ("socket init", result);
+
+  nsCOMPtr<IcedTeaSocketListener> listener = new IcedTeaSocketListener (this);
+  result = socket->AsyncListen (listener);
+  PLUGIN_CHECK ("add socket listener", result);
+
+  result = StartAppletviewer ();
+  PLUGIN_CHECK ("started appletviewer", result);
+
+  while (!IsConnected()) 
+  {
+      result = curr_thread->ProcessNextEvent (PR_TRUE, &processed);
+      PLUGIN_CHECK ("wait for connection: process next event", result);
+  }
+
+}
+
 NS_IMETHODIMP
 IcedTeaPluginFactory::Shutdown ()
 {
@@ -1297,6 +1420,7 @@
   PRInt32 exitVal;
   applet_viewer_process->GetExitValue(&exitVal);
 
+/*
   PRUint32 max_sleep_time = 2000;
   PRUint32 sleep_time = 0;
   while ((sleep_time < max_sleep_time) && (exitVal == -1)) {
@@ -1312,6 +1436,7 @@
 	  printf("Appletviewer still appears to be running. Trying to kill it...\n");
 	  applet_viewer_process->Kill();
   }
+*/
 
   return NS_OK;
 }
@@ -1949,6 +2074,15 @@
 NS_IMETHODIMP
 IcedTeaPluginInstance::GetPeer (nsIPluginInstancePeer** aPeer)
 {
+
+  PRBool processed;
+  nsresult result;
+  while (!peer)
+    {
+      result = factory->current->ProcessNextEvent(PR_TRUE, &processed);
+      PLUGIN_CHECK_RETURN ("wait for peer: process next event", result);
+    }
+
   printf ("GETTING PEER!!!: %p\n", peer);
   *aPeer = peer;
   // FIXME: where is this unref'd?
@@ -2261,76 +2395,6 @@
   return NS_OK;
 }
 
-#include <nsIServerSocket.h>
-#include <nsNetError.h>
-#include <nsPIPluginInstancePeer.h>
-#include <nsIPluginInstanceOwner.h>
-#include <nsIRunnable.h>
-#include <iostream>
-
-class IcedTeaRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIRUNNABLE
-
-  IcedTeaRunnable ();
-
-  ~IcedTeaRunnable ();
-};
-
-NS_IMPL_ISUPPORTS1 (IcedTeaRunnable, nsIRunnable)
-
-IcedTeaRunnable::IcedTeaRunnable ()
-{
-}
-
-IcedTeaRunnable::~IcedTeaRunnable ()
-{
-}
-
-NS_IMETHODIMP
-IcedTeaRunnable::Run ()
-{
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-template <class T>
-class IcedTeaRunnableMethod : public IcedTeaRunnable
-{
-public:
-  typedef void (T::*Method) ();
-
-  IcedTeaRunnableMethod (T* object, Method method);
-  NS_IMETHOD Run ();
-
-  ~IcedTeaRunnableMethod ();
-
-  T* object;
-  Method method;
-};
-
-template <class T>
-IcedTeaRunnableMethod<T>::IcedTeaRunnableMethod (T* object, Method method)
-: object (object),
-  method (method)
-{
-  NS_ADDREF (object);
-}
-
-template <class T>
-IcedTeaRunnableMethod<T>::~IcedTeaRunnableMethod ()
-{
-  NS_RELEASE (object);
-}
-
-template <class T> NS_IMETHODIMP
-IcedTeaRunnableMethod<T>::Run ()
-{
-  (object->*method) ();
-  return NS_OK;
-}
-
 void
 IcedTeaPluginFactory::HandleMessage (nsCString const& message)
 {
@@ -2401,6 +2465,7 @@
                 do_QueryInterface (instance->peer);
               nsIPluginInstanceOwner* owner = nsnull;
               ownerGetter->GetOwner (&owner);
+			  printf("Calling GetURL with %s and %s\n", nsCString (url).get (), nsCString (target).get ());
               owner->GetURL (nsCString (url).get (),
                              nsCString (target).get (),
                              nsnull, 0, nsnull, 0);
@@ -2592,7 +2657,8 @@
         }
       else if (command == "Error")
         {
-			// FIXME: Not yet implemented
+			printf("Error occured. Setting error flag for container @ %d to true\n", reference);
+			resultMap[reference]->errorOccured = PR_TRUE;
 		}
     }
   else if (prefix == "context")
@@ -3106,7 +3172,17 @@
 {
   PLUGIN_TRACE_INSTANCE ();
 
-  printf("Getting ready... %s %d\n", message.get(), message.Length() + 1);
+  nsresult result;
+  PRBool processed;
+
+  // while outputstream is not yet ready, process next event
+  while (!output)
+    {
+      result = current->ProcessNextEvent(PR_TRUE, &processed);
+      PLUGIN_CHECK_RETURN ("wait for output stream initialization: process next event", result);
+    }
+
+  printf("Writing to JVM: %s\n", message.get());
 
 /*
  * JNI I/O code
@@ -3125,7 +3201,7 @@
   // FIXME: check that message is a valid UTF-8 string.
   //  printf ("MESSAGE: %s\n", message.get ());
   message.Insert('-',0);
-  nsresult result = output->Write (message.get (),
+  result = output->Write (message.get (),
                                    message.Length () + 1,
                                    &writeCount);
   PLUGIN_CHECK_RETURN ("wrote bytes", result);
@@ -3515,7 +3591,7 @@
 PRBool
 IcedTeaPluginFactory::IsConnected ()
 {
-  PLUGIN_TRACE_INSTANCE ();
+//  PLUGIN_TRACE_INSTANCE ();
   return connected;
 }
 
@@ -3543,6 +3619,22 @@
   PLUGIN_CHECK_RETURN ("set transport", result);
   factory->Connected ();
 
+  result = aTransport->OpenOutputStream (nsITransport::OPEN_BLOCKING,
+                                        nsnull, nsnull,
+                                        getter_AddRefs (factory->output));
+  PLUGIN_CHECK_RETURN ("output stream", result);
+
+  result = aTransport->OpenInputStream (0, nsnull, nsnull,
+                                       getter_AddRefs (factory->input));
+  PLUGIN_CHECK_RETURN ("input stream", result);
+
+  factory->async = do_QueryInterface (factory->input, &result);
+  PLUGIN_CHECK_RETURN ("async input stream", result);
+
+  result = factory->async->AsyncWait (factory, 0, 0, factory->current);
+  PLUGIN_CHECK_RETURN ("add async wait", result);
+
+
   return NS_OK;
 }
 
@@ -3553,11 +3645,15 @@
 {
   PLUGIN_TRACE_LISTENER ();
 
+  nsCString shutdownStr("shutdown");
+  printf("stop listening: %uld\n", aStatus);
+
   nsresult result = NS_OK;
 
   switch (aStatus)
   {
   case NS_ERROR_ABORT:
+    factory->SendMessageToAppletViewer(shutdownStr);
     PLUGIN_DEBUG ("appletviewer stopped");
     // FIXME: privatize?
     result = factory->async->AsyncWait (nsnull, 0, 0, factory->current);
@@ -4660,13 +4756,6 @@
   if (!aClass.Equals (PluginCID))
     return NS_ERROR_FACTORY_NOT_LOADED;
 
-  IcedTeaPluginFactory* factory = new IcedTeaPluginFactory ();
-  if (!factory)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF (factory);
-  *aFactory = factory;
-
   // Set appletviewer_executable.
   Dl_info info;
   char* filename = NULL;
@@ -4701,6 +4790,29 @@
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
+  if (factory_created == PR_TRUE)
+  {
+	  // wait for factory to initialize
+	  while (!factory)
+	  {
+		  PR_Sleep(200);
+		  PLUGIN_DEBUG("Waiting for factory to be created...");
+	  }
+
+	  *aFactory = factory;
+	  NS_ADDREF (factory);
+  } else
+  {
+    factory_created = PR_TRUE;
+    PLUGIN_DEBUG("Creating factory");
+    factory = new IcedTeaPluginFactory ();
+    if (!factory)
+      return NS_ERROR_OUT_OF_MEMORY;
+
+    NS_ADDREF (factory);
+    *aFactory = factory;
+  }
+
   return NS_OK;
 }
 
--- a/patches/icedtea-liveconnect.patch	Mon Sep 01 10:36:56 2008 +0200
+++ b/patches/icedtea-liveconnect.patch	Fri Sep 05 12:11:57 2008 -0400
@@ -1,6 +1,6 @@
 diff -urN openjdk.orig/jdk/make/sun/Makefile openjdk/jdk/make/sun/Makefile
 --- openjdk.orig/jdk/make/sun/Makefile	2008-07-10 15:54:44.000000000 -0400
-+++ openjdk/jdk/make/sun/Makefile	2008-08-19 16:15:28.000000000 -0400
++++ openjdk/jdk/make/sun/Makefile	2008-08-26 17:23:07.000000000 -0400
 @@ -66,6 +66,7 @@
            $(HEADLESS_SUBDIR) $(DGA_SUBDIR) \
  	  font jpeg cmm applet rmi beans $(JDBC_SUBDIR) \
@@ -11,7 +11,7 @@
  all build clean clobber::
 diff -urN openjdk.orig/jdk/make/sun/Makefile.orig openjdk/jdk/make/sun/Makefile.orig
 --- openjdk.orig/jdk/make/sun/Makefile.orig	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/make/sun/Makefile.orig	2008-08-19 16:15:28.000000000 -0400
++++ openjdk/jdk/make/sun/Makefile.orig	2008-08-26 17:23:07.000000000 -0400
 @@ -0,0 +1,73 @@
 +#
 +# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
@@ -88,7 +88,7 @@
 +
 diff -urN openjdk.orig/jdk/make/sun/plugin/Makefile openjdk/jdk/make/sun/plugin/Makefile
 --- openjdk.orig/jdk/make/sun/plugin/Makefile	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/make/sun/plugin/Makefile	2008-08-19 16:15:28.000000000 -0400
++++ openjdk/jdk/make/sun/plugin/Makefile	2008-08-26 17:23:07.000000000 -0400
 @@ -0,0 +1,53 @@
 +#
 +# Copyright 1995-2005 Sun Microsystems, Inc.  All Rights Reserved.
@@ -145,7 +145,7 @@
 +
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java	2008-08-21 13:23:32.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/GetMemberPluginCallRequest.java	2008-07-20 22:33:37.000000000 -0400
 @@ -0,0 +1,58 @@
 +/* GetMemberPluginCallRequest -- represent Java-to-JavaScript requests
 +   Copyright (C) 2008  Red Hat
@@ -207,7 +207,7 @@
 +
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java	2008-08-21 13:23:32.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/GetWindowPluginCallRequest.java	2008-07-20 22:33:34.000000000 -0400
 @@ -0,0 +1,56 @@
 +/* GetWindowPluginCallRequest -- represent Java-to-JavaScript requests
 +   Copyright (C) 2008  Red Hat
@@ -267,7 +267,7 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java openjdk/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java	2008-08-21 13:23:33.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletSecurityContext.java	2008-09-04 17:01:37.000000000 -0400
 @@ -0,0 +1,807 @@
 +/* PluginAppletSecurityContext -- execute plugin JNI messages
 +   Copyright (C) 2008  Red Hat
@@ -1066,7 +1066,7 @@
 +		} catch (Throwable t) {
 +			t.printStackTrace();
 +			throwable = t;
-+			PluginException p = new PluginException(reference, t);
++			PluginException p = new PluginException(identifier, reference, t);
 +		}
 +	}
 +
@@ -1078,8 +1078,8 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginAppletViewer.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java	2008-08-21 13:23:33.000000000 -0400
-@@ -0,0 +1,1384 @@
++++ openjdk/jdk/src/share/classes/sun/applet/PluginAppletViewer.java	2008-09-04 17:01:38.000000000 -0400
+@@ -0,0 +1,1416 @@
 + /*
 +  * Copyright 1995-2004 Sun Microsystems, Inc.  All Rights Reserved.
 +  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -1213,6 +1213,7 @@
 + 		AppletViewerPanel.debug("Unable to start NetX applet - defaulting to Sun applet", ex);
 + 		panel = new AppletViewerPanel(doc, atts);
 + 	}
++
 + 	add("Center", panel);
 + 	panel.init();
 + 	appletPanels.addElement(panel);
@@ -1307,6 +1308,11 @@
 +
 +         try {
 +        	 if (message.startsWith("tag")) {
++        		 
++        		 // tag and handle must both be set before parsing, so we need
++        		 // synchronization here, as the setting of these variables
++        		 // may happen in independent threads
++        		 
 +        		 synchronized(requests) {
 +        			 PluginParseRequest request = requests.get(identifier);
 +        			 if (request == null) {
@@ -1369,12 +1375,14 @@
 +     public void handleMessage(int reference, String message)
 +     {
 +         if (message.startsWith("width")) {
-+             int width =
-+                 Integer.parseInt(message.substring("width".length() + 1));
++        	 int width =
++        		 Integer.parseInt(message.substring("width".length() + 1));
++             panel.setAppletSizeIfNeeded(width, -1);
 +             setSize(width, getHeight());
 +         } else if (message.startsWith("height")) {
-+             int height =
-+                 Integer.parseInt(message.substring("height".length() + 1));
++             int height = 
++            	 Integer.parseInt(message.substring("height".length() + 1));
++             panel.setAppletSizeIfNeeded(-1, height);
 +             setSize(getWidth(), height);
 +         } else if (message.startsWith("destroy")) {
 +             dispose();
@@ -2215,7 +2223,7 @@
 + 		skipSpace(in);
 + 		val = buf.toString();
 + 	    }
-+ 	    //statusMsgStream.println("PUT " + att + " = '" + val + "'");
++ 	    System.err.println("PUT " + att + " = '" + val + "'");
 + 	    if (! val.equals("")) {
 + 		atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
 + 	    }
@@ -2364,6 +2372,14 @@
 + 		    else if (nm.equalsIgnoreCase("applet")) {
 +                         isAppletTag = true;
 + 			atts = scanTag(in);
++ 			
++ 			// If there is a classid present, transform it to code tag
++            if (atts.get("code") == null && atts.get("classid") != null && 
++            		((String) atts.get("classid")).startsWith("java:")) {
++              	 //skip "java:"
++              	 atts.put("code", ((String) atts.get("classid")).substring(5));
++               }
++
 + 			if (atts.get("code") == null && atts.get("object") == null) {
 + 			    statusMsgStream.println(appletRequiresCodeWarning);
 + 			    atts = null;
@@ -2378,12 +2394,21 @@
 + 		    else if (nm.equalsIgnoreCase("object")) {
 +                         isObjectTag = true;
 + 			atts = scanTag(in);
++                         
++ 						// If there is a classid present, transform it to code tag
++                         if (atts.get("code") == null && atts.get("classid") != null && 
++                        		 ((String) atts.get("classid")).startsWith("java:")) {
++                        	 //skip "java:"
++                        	 atts.put("code", ((String) atts.get("classid")).substring(5));
++                         }
++
 +                         // The <OBJECT> attribute codebase isn't what
-+                         // we want. If its defined, remove it.
-+                         if(atts.get("codebase") != null) {
-+                             atts.remove("codebase");
++                         // we want when not dealing with jars. If its 
++                         // defined, remove it in that case.
++                         if(atts.get("archive") == null && atts.get("codebase") != null) {
++                       		atts.remove("codebase");
 +                         }
-+ 
++
 +                         if (atts.get("width") == null) {
 + 			    statusMsgStream.println(objectRequiresWidthWarning);
 + 			    atts = null;
@@ -2396,6 +2421,13 @@
 +                         isEmbedTag = true;
 + 			atts = scanTag(in);
 + 
++ 			// If there is a classid present, transform it to code tag
++            if (atts.get("code") == null && atts.get("classid") != null && 
++            		((String) atts.get("classid")).startsWith("java:")) {
++           	 //skip "java:"
++           	 atts.put("code", ((String) atts.get("classid")).substring(5));
++            }
++
 + 			if (atts.get("code") == null && atts.get("object") == null) {
 + 			    statusMsgStream.println(embedRequiresCodeWarning);
 + 			    atts = null;
@@ -2466,7 +2498,7 @@
 + }
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/PluginCallRequest.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginCallRequest.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginCallRequest.java	2008-08-21 13:23:33.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginCallRequest.java	2008-07-20 22:33:36.000000000 -0400
 @@ -0,0 +1,54 @@
 +/* PluginCallRequest -- represent Java-to-JavaScript requests
 +   Copyright (C) 2008  Red Hat
@@ -2524,7 +2556,7 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginDebug.java openjdk/jdk/src/share/classes/sun/applet/PluginDebug.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginDebug.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginDebug.java	2008-08-21 13:23:34.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginDebug.java	2008-08-15 15:19:49.000000000 -0400
 @@ -0,0 +1,13 @@
 +package sun.applet;
 +
@@ -2541,24 +2573,24 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginException.java openjdk/jdk/src/share/classes/sun/applet/PluginException.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginException.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginException.java	2008-08-21 13:23:34.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginException.java	2008-09-04 17:01:38.000000000 -0400
 @@ -0,0 +1,12 @@
 +package sun.applet;
 +
 +public class PluginException extends Exception {
 +
-+	public PluginException (int instance, Throwable t) {
++	public PluginException (int instance, int reference, Throwable t) {
 +		t.printStackTrace();
 +		this.setStackTrace(t.getStackTrace());
 +		
-+		String message = "instance " + instance + " Error " + t.getMessage();
++		String message = "instance " + instance + " reference " + reference + " Error " + t.getMessage();
 +		PluginMain.write(message);
 +	}
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java openjdk/jdk/src/share/classes/sun/applet/PluginMain.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMain.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginMain.java	2008-08-21 13:49:53.000000000 -0400
-@@ -0,0 +1,474 @@
++++ openjdk/jdk/src/share/classes/sun/applet/PluginMain.java	2008-09-04 17:01:38.000000000 -0400
+@@ -0,0 +1,485 @@
 +/*
 + * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -2638,7 +2670,9 @@
 +	static LinkedList<String> writeQueue = new LinkedList<String>();
 +
 +	static PluginMessageConsumer consumer;
-+	static boolean shuttingDown = false;
++	static Boolean shuttingDown = false;
++	
++	static final boolean redirectStreams = false;
 +
 +    /**
 +     * The main entry point into AppletViewer.
@@ -2660,19 +2694,19 @@
 +    		System.exit(1);
 +    	}
 +
-+/*
-+    	try {
-+    		File errFile = new File("/tmp/java.stderr");
-+    		File outFile = new File("/tmp/java.stdout");
-+
-+    		System.setErr(new PrintStream(new FileOutputStream(errFile)));
-+    		System.setOut(new PrintStream(new FileOutputStream(outFile)));
-+
-+    	} catch (Exception e) {
-+    		System.err.println("Unable to redirect streams");
-+    		e.printStackTrace();
++    	if (redirectStreams) {
++    		try {
++    			File errFile = new File("/tmp/java.stderr");
++    			File outFile = new File("/tmp/java.stdout");
++
++    			System.setErr(new PrintStream(new FileOutputStream(errFile)));
++    			System.setOut(new PrintStream(new FileOutputStream(outFile)));
++
++    		} catch (Exception e) {
++    			System.err.println("Unable to redirect streams");
++    			e.printStackTrace();
++    		}
 +    	}
-+*/
 +
 +    	// INSTALL THE SECURITY MANAGER
 +    	init();
@@ -2859,7 +2893,7 @@
 +    			PluginAppletSecurityContext.handleMessage(identifier, reference, rest);
 +    		}
 +    	} catch (Exception e) {
-+    		throw new PluginException(identifier, e);
++    		throw new PluginException(identifier, reference, e);
 +    	}
 +    }
 +
@@ -2973,9 +3007,16 @@
 +        	} catch (IOException e) {
 +        		// if we are shutting down, ignore write failures as 
 +        		// pipe may have closed
-+        		if (!shuttingDown) {
-+        			throw new RuntimeException(e);
++        		synchronized(shuttingDown) {
++        			if (!shuttingDown) {
++        				e.printStackTrace();
++        			}
 +        		}
++
++        		// either ways, if the pipe is broken, there is nothing 
++        		// we can do anymore. Don't hang around.
++        		System.err.println("Unable to write to PIPE. APPLETVIEWER exiting");        		
++        		System.exit(1);
 +        	}
 +		}
 +
@@ -3017,7 +3058,9 @@
 +    	String message = pluginInputTokenizer.sval;
 +    	PluginDebug.debug("  PIPE: appletviewer read: " + message);
 +    	if (message == null || message.equals("shutdown")) {
-+    		shuttingDown = true;
++    		synchronized(shuttingDown) {
++    			shuttingDown = true;
++    		}
 +    		try {
 +    			// Close input/output channels to plugin.
 +    			pluginInputReader.close();
@@ -3035,8 +3078,8 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java openjdk/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java	2008-08-21 13:23:35.000000000 -0400
-@@ -0,0 +1,46 @@
++++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageConsumer.java	2008-09-04 17:01:39.000000000 -0400
+@@ -0,0 +1,49 @@
 +package sun.applet;
 +
 +import java.util.ArrayList;
@@ -3072,20 +3115,23 @@
 +		
 +		// FIXME: Can be made more efficient by having an idle worker pool
 +		
-+		for (PluginMessageHandlerWorker worker: workers) {
-+			if (worker.isFree()) {
-+				PluginDebug.debug("Found free worker with id " + worker.getWorkerId());
-+				return worker;
++		while (true) {
++			for (PluginMessageHandlerWorker worker: workers) {
++				if (worker.isFree()) {
++					PluginDebug.debug("Found free worker with id " + worker.getWorkerId());
++					return worker;
++				}
 +			}
++			Thread.yield();
 +		}
-+		
-+		throw new RuntimeException("Out of message handler workers");
++
++		//throw new RuntimeException("Out of message handler workers");
 +	}
 +	
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java openjdk/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java	2008-08-21 13:23:35.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginMessageHandlerWorker.java	2008-08-19 15:47:52.000000000 -0400
 @@ -0,0 +1,59 @@
 +package sun.applet;
 +
@@ -3148,7 +3194,7 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/PluginObjectStore.java openjdk/jdk/src/share/classes/sun/applet/PluginObjectStore.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/PluginObjectStore.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/PluginObjectStore.java	2008-08-21 13:23:35.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/PluginObjectStore.java	2008-08-13 16:37:22.000000000 -0400
 @@ -0,0 +1,119 @@
 +/* PluginObjectStore -- manage identifier-to-object mapping
 +   Copyright (C) 2008  Red Hat
@@ -3271,7 +3317,7 @@
 +
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/TestEnv.java openjdk/jdk/src/share/classes/sun/applet/TestEnv.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/TestEnv.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/TestEnv.java	2008-08-21 13:23:36.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/TestEnv.java	2008-07-20 22:33:36.000000000 -0400
 @@ -0,0 +1,172 @@
 +/* TestEnv -- test JavaScript-to-Java calls
 +   Copyright (C) 2008  Red Hat
@@ -3447,7 +3493,7 @@
 +}
 diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java openjdk/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java
 --- openjdk.orig/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java	1969-12-31 19:00:00.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java	2008-08-21 13:23:36.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/VoidPluginCallRequest.java	2008-07-20 22:33:36.000000000 -0400
 @@ -0,0 +1,49 @@
 +/* VoidPluginCallRequest -- represent Java-to-JavaScript requests
 +   Copyright (C) 2008  Red Hat
--- a/patches/icedtea-webstart.patch	Mon Sep 01 10:36:56 2008 +0200
+++ b/patches/icedtea-webstart.patch	Fri Sep 05 12:11:57 2008 -0400
@@ -1,6 +1,6 @@
-diff -c openjdk.orig/jdk/make/launchers/Makefile openjdk/jdk/make/launchers/Makefile
---- openjdk.orig/jdk/make/launchers/Makefile	2008-06-29 09:45:56.000000000 -0400
-+++ openjdk/jdk/make/launchers/Makefile	2008-06-29 09:47:01.000000000 -0400
+diff -ur openjdk.orig/jdk/make/launchers/Makefile openjdk/jdk/make/launchers/Makefile
+--- openjdk.orig/jdk/make/launchers/Makefile	2008-07-10 15:54:41.000000000 -0400
++++ openjdk/jdk/make/launchers/Makefile	2008-09-04 17:50:22.000000000 -0400
 @@ -67,6 +67,7 @@
  $(call make-launcher, javadoc, com.sun.tools.javadoc.Main, , )
  $(call make-launcher, javah, com.sun.tools.javah.Main, , )
@@ -9,10 +9,125 @@
  $(call make-launcher, jconsole, sun.tools.jconsole.JConsole, \
    -J-Djconsole.showOutputViewer, )
  $(call make-launcher, jdb, com.sun.tools.example.debug.tty.TTY, , )
-diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/AppletViewerPanel.java openjdk/jdk/src/share/classes/sun/applet/AppletViewerPanel.java
---- openjdk.orig/jdk/src/share/classes/sun/applet/AppletViewerPanel.java	2008-01-12 15:53:45.000000000 -0500
-+++ openjdk/jdk/src/share/classes/sun/applet/AppletViewerPanel.java	2008-02-04 11:51:20.000000000 -0500
-@@ -42,25 +42,25 @@
+diff -ur openjdk.orig/jdk/src/share/classes/sun/applet/AppletPanel.java openjdk/jdk/src/share/classes/sun/applet/AppletPanel.java
+--- openjdk.orig/jdk/src/share/classes/sun/applet/AppletPanel.java	2008-07-10 15:57:10.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/AppletPanel.java	2008-09-04 17:54:34.000000000 -0400
+@@ -42,9 +42,6 @@
+ import java.net.UnknownHostException;
+ import java.security.*;
+ import java.util.*;
+-import java.util.Collections;
+-import java.util.Locale;
+-import java.util.WeakHashMap;
+ import javax.swing.SwingUtilities;
+ import sun.awt.AppContext;
+ import sun.awt.EmbeddedFrame;
+@@ -68,7 +65,7 @@
+     /**
+      * The applet (if loaded).
+      */
+-    Applet applet;
++    protected Applet applet;
+ 
+     /**
+      * Applet will allow initialization.  Should be
+@@ -117,7 +114,7 @@
+     /**
+      * The thread for the applet.
+      */
+-    Thread handler;
++    protected Thread handler;
+ 
+ 
+     /**
+@@ -162,7 +159,8 @@
+      * Creates a thread to run the applet. This method is called
+      * each time an applet is loaded and reloaded.
+      */
+-    synchronized void createAppletThread() {
++	//Overridden by NetxPanel.
++    protected synchronized void createAppletThread() {
+         // Create a thread group for the applet, and start a new
+         // thread to load the applet.
+         String nm = "applet-" + getCode();
+@@ -306,7 +304,7 @@
+     /**
+      * Get an event from the queue.
+      */
+-    synchronized AppletEvent getNextEvent() throws InterruptedException {
++    protected synchronized AppletEvent getNextEvent() throws InterruptedException {
+         while (queue == null || queue.isEmpty()) {
+             wait();
+         }
+@@ -499,9 +497,25 @@
+ 
+                       status = APPLET_START;
+                       showAppletStatus("started");
++
++                      // reset size to make up for applets that specify height in %
++                      try {
++                    	  javax.swing.SwingUtilities.invokeLater(new Runnable() {
++                    		  public void run() {
++                    			  int width = getWidth();
++                    			  int height = getHeight();
++
++                    			  appletResize(width, height);
++                    			  validate();
++                    		  }
++                    	  });
++                      } catch (Exception e) {
++                    	  System.err.println("Applet resize failed.");
++                    	  e.printStackTrace();
++                      }
++
+                       break;
+                   }
+-
+                 case APPLET_STOP:
+                     if (status != APPLET_START) {
+                         showAppletStatus("notstarted");
+@@ -695,7 +709,8 @@
+      * applet event processing so that it can be gracefully interrupted from
+      * things like HotJava.
+      */
+-    private void runLoader() {
++	//Overridden by NetxPanel.
++    protected void runLoader() {
+         if (status != APPLET_DISPOSE) {
+             showAppletStatus("notdisposed");
+             return;
+@@ -892,8 +907,8 @@
+         return status == APPLET_START;
+     }
+ 
+-
+     private EventQueue appEvtQ = null;
++
+     /**
+      * Is called when the applet wants to be resized.
+      */
+diff -ur openjdk.orig/jdk/src/share/classes/sun/applet/AppletViewerPanel.java openjdk/jdk/src/share/classes/sun/applet/AppletViewerPanel.java
+--- openjdk.orig/jdk/src/share/classes/sun/applet/AppletViewerPanel.java	2008-07-10 15:57:10.000000000 -0400
++++ openjdk/jdk/src/share/classes/sun/applet/AppletViewerPanel.java	2008-09-04 17:54:42.000000000 -0400
+@@ -25,13 +25,11 @@
+ 
+ package sun.applet;
+ 
+-import java.util.*;
+-import java.io.*;
+-import java.net.URL;
++import java.applet.AppletContext;
++import java.awt.Dimension;
+ import java.net.MalformedURLException;
+-import java.awt.*;
+-import java.applet.*;
+-import sun.tools.jar.*;
++import java.net.URL;
++import java.util.Hashtable;
+ 
+ 
+ /**
+@@ -42,35 +40,37 @@
   *
   * @author      Arthur van Hoff
   */
@@ -21,7 +136,7 @@
  
      /* Are we debugging? */
 -    static boolean debug = false;
-+    protected static boolean debug = false;
++    protected static boolean debug = true;
  
      /**
       * The document url.
@@ -43,7 +158,11 @@
  
      /*
       * JDK 1.1 serialVersionUID
-@@ -70,7 +70,7 @@
+      */
+     private static final long serialVersionUID = 8890989370785545619L;
+ 
++    private Dimension windowSizeFactor = new Dimension(750, 350);
++    
      /**
       * Construct an applet viewer and start the applet.
       */
@@ -52,7 +171,75 @@
          this.documentURL = documentURL;
          this.atts = atts;
  
-@@ -202,12 +202,12 @@
+@@ -102,6 +102,7 @@
+ 
+     }
+ 
++
+     /**
+      * Get an applet parameter.
+      */
+@@ -125,12 +126,42 @@
+     }
+ 
+     /**
++     * Set applet size (as proportion of window size) if needed
++     */
++    public synchronized void setAppletSizeIfNeeded(int width, int height) {
++
++    	Dimension newD = new Dimension(getWidth(), getHeight());
++
++    	String h = getParameter("height");
++    	String w = getParameter("width");
++
++    	if (width != -1 && w != null && w.endsWith("%")) {
++    		newD.width = (Integer.valueOf(w.substring(0, w.length() - 1)).intValue()/100)*width;
++    	}
++
++    	if (height != -1 && h != null && h.endsWith("%")) {
++    		newD.height = (Integer.valueOf(h.substring(0, h.length() - 1)).intValue()/100)*height;
++    	}
++    	
++    	synchronized(windowSizeFactor) {
++    		windowSizeFactor = newD;
++    	}
++    }
++
++    /**
+      * Get the width.
+      */
+     public int getWidth() {
+         String w = getParameter("width");
+         if (w != null) {
+-            return Integer.valueOf(w).intValue();
++        	try {
++        		return Integer.valueOf(w).intValue();
++        	} catch (NumberFormatException nfe) {
++        		synchronized(windowSizeFactor) {
++        			System.err.println("getWidth() returning " + windowSizeFactor.width);
++        			return windowSizeFactor.width;
++        		}
++        	}
+         }
+         return 0;
+     }
+@@ -142,7 +173,14 @@
+     public int getHeight() {
+         String h = getParameter("height");
+         if (h != null) {
+-            return Integer.valueOf(h).intValue();
++        	try {
++        		return Integer.valueOf(h).intValue();
++        	} catch (NumberFormatException nfe) {
++        		synchronized(windowSizeFactor) {
++        			System.err.println("getHeight() returning " + windowSizeFactor.height);
++        			return windowSizeFactor.height;
++        		}
++        	}
+         }
+         return 0;
+     }
+@@ -202,12 +240,12 @@
          return (AppletContext)getParent();
      }
  
@@ -67,53 +254,3 @@
          if(debug) {
              t.printStackTrace();
              debug(s);
-diff -urN openjdk.orig/jdk/src/share/classes/sun/applet/AppletPanel.java openjdk/jdk/src/share/classes/sun/applet/AppletPanel.java
---- openjdk.orig/jdk/src/share/classes/sun/applet/AppletPanel.java	2008-03-26 04:58:12.000000000 -0400
-+++ openjdk/jdk/src/share/classes/sun/applet/AppletPanel.java	2008-04-07 21:55:56.000000000 -0400
-@@ -68,7 +68,7 @@
-     /**
-      * The applet (if loaded).
-      */
--    Applet applet;
-+    protected Applet applet;
- 
-     /**
-      * Applet will allow initialization.  Should be
-@@ -117,7 +117,7 @@
-     /**
-      * The thread for the applet.
-      */
--    Thread handler;
-+    protected Thread handler;
- 
- 
-     /**
-@@ -162,7 +162,8 @@
-      * Creates a thread to run the applet. This method is called
-      * each time an applet is loaded and reloaded.
-      */
--    synchronized void createAppletThread() {
-+	//Overridden by NetxPanel.
-+    protected synchronized void createAppletThread() {
-         // Create a thread group for the applet, and start a new
-         // thread to load the applet.
-         String nm = "applet-" + getCode();
-@@ -306,7 +307,7 @@
-     /**
-      * Get an event from the queue.
-      */
--    synchronized AppletEvent getNextEvent() throws InterruptedException {
-+    protected synchronized AppletEvent getNextEvent() throws InterruptedException {
-         while (queue == null || queue.isEmpty()) {
-             wait();
-         }
-@@ -695,7 +696,8 @@
-      * applet event processing so that it can be gracefully interrupted from
-      * things like HotJava.
-      */
--    private void runLoader() {
-+	//Overridden by NetxPanel.
-+    protected void runLoader() {
-         if (status != APPLET_DISPOSE) {
-             showAppletStatus("notdisposed");
-             return;
--- a/rt/net/sourceforge/jnlp/NetxPanel.java	Mon Sep 01 10:36:56 2008 +0200
+++ b/rt/net/sourceforge/jnlp/NetxPanel.java	Fri Sep 05 12:11:57 2008 -0400
@@ -57,13 +57,15 @@
     				getWidth(), 
     				getHeight(), 
     				atts);
-    		
-    		//The custom NetX Policy and SecurityManager are set here.
-    		if (!JNLPRuntime.isInitialized()) {
-    			System.out.println("initializing JNLPRuntime...");
-    			JNLPRuntime.initialize();
-    		} else {
-    			System.out.println("JNLPRuntime already initialized");
+
+    		synchronized(JNLPRuntime.initMutex) {
+    			//The custom NetX Policy and SecurityManager are set here.
+    			if (!JNLPRuntime.isInitialized()) {
+    				System.out.println("initializing JNLPRuntime...");
+    				JNLPRuntime.initialize();
+    			} else {
+    				System.out.println("JNLPRuntime already initialized");
+    			}
     		}
 
     		doInit = true;
--- a/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Mon Sep 01 10:36:56 2008 +0200
+++ b/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Sep 05 12:11:57 2008 -0400
@@ -90,7 +90,9 @@
 
     /** whether debug mode is on */
     private static boolean debug = false; // package access by Boot
-
+    
+    /** mutex to wait on, for initialization */
+    public static Object initMutex = new Object();
 
     /**
      * Returns whether the JNLP runtime environment has been
@@ -114,7 +116,6 @@
      */
     public static void initialize() throws IllegalStateException {
         checkInitialized();
-        initialized = true;
 
         if (headless == false)
             checkHeadless();
@@ -143,6 +144,8 @@
         }
 
         ServiceManager.setServiceManagerStub(new XServiceManagerStub()); // ignored if we're running under Web Start
+
+        initialized = true;
     }
 
     /**