changeset 2007:5e20e6468dd1

Updates to the new NP plugin: - Added preliminary array support (get/set from JS->Java) - Fixed some timing issues to make plugin faster - Implemented object resuse so that comparison of Java objects on JS side works * plugin/icedteanp/IcedTeaJavaRequestProcessor.cc (newMessageOnBus): Handle certain callbacks in a more uniform manner. (postAndWaitForResponse): Lower poll time to 200 us for more responsiveness. (findClass): Accept instance ID which is used for searching classes in specific applet instance classloaders. (getArrayLength): New function. Returns length of an array on Java side. (getSlot): New function. Returns element at requested index in an array. (setSlot): New function. Sets requested index in array to supplied value. (getField): Accept object id. (getStaticField): Fix parameter ordering for consistency. (set): New function. Sets Java side fields to given value. (setStaticField): New function. Sets value of a static field in a Java object. (setField): New function. Sets value of a static field in a class. (createJavaObjectFromVariant): Handle void and null variants. Handle case where object is already created. (call): Use a string to store object id. (newObject): Same. (hasPackage): Accept instance id and pass it on. * plugin/icedteanp/IcedTeaJavaRequestProcessor.h: Relevant changes as needed by the updates to the .cc file. * plugin/icedteanp/IcedTeaNPPlugin.cc (get_scriptable_object): Pass false for the new isArray arg to get_scriptable_java_object. * plugin/icedteanp/IcedTeaPluginRequestProcessor.cc: Pass 0 as the instance id to all findClass calls. * plugin/icedteanp/IcedTeaScriptablePluginObject.cc: Reuse Java object pointers. (IcedTeaScriptableJavaPackageObject::hasProperty): Pass the instance id to findClass. (get_scriptable_java_object): Update code so that Java object pointers can be reused. (IcedTeaScriptableJavaObject::setIsArray): New function. Sets if this object represents an array. (IcedTeaScriptableJavaObject::getIsArray): New function. Returns if this object represents an array. (IcedTeaScriptableJavaObject::hasMethod): Bypass "array indexes" passed to the method. (IcedTeaScriptableJavaObject::javaResultToNPVariant): Handle void and null values correctly. Handle array objects. (IcedTeaScriptableJavaObject::invoke): Set exceptions in JS engine if one occurred on Java side. (IcedTeaScriptableJavaObject::hasProperty): Handle array length and index properties. (IcedTeaScriptableJavaObject::getProperty): Same. (IcedTeaScriptableJavaObject::setProperty): Add support for setting array index values. * plugin/icedteanp/IcedTeaScriptablePluginObject.h: Changes as necessitated by changes to the .cc file. * plugin/icedteanp/java/sun/applet/JavaConsole.java: Handle changed API in PluginAppletSecurityContext. * plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java (getMatchingMethod): Handle un-castable/deferred casts. (getMatchingConstructor): Same. (getNum): Fix handling for characters. * plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java (associateInstance): New function. Associated a loader with an instance. (getLoaderInfo): New function. Returns loader info in a map. (handleMessage): Look for class in instance specific loaders as well. Handle float/double precision upto 308 (E308 is max for double). * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (AppletEventListener::appletStateChanged): Fix race condition during initialization. (handleMessage): Fix race condition to handle GetJavaObject calls when panel is still being initialized.
author Deepak Bhole <dbhole@redhat.com>
date Tue, 15 Sep 2009 12:47:59 -0400
parents 5edc8307c7ab
children 175529fae103
files ChangeLog plugin/icedteanp/IcedTeaJavaRequestProcessor.cc plugin/icedteanp/IcedTeaJavaRequestProcessor.h plugin/icedteanp/IcedTeaNPPlugin.cc plugin/icedteanp/IcedTeaPluginRequestProcessor.cc plugin/icedteanp/IcedTeaScriptablePluginObject.cc plugin/icedteanp/IcedTeaScriptablePluginObject.h plugin/icedteanp/java/sun/applet/JavaConsole.java plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
diffstat 11 files changed, 864 insertions(+), 331 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Aug 27 13:16:24 2009 -0400
+++ b/ChangeLog	Tue Sep 15 12:47:59 2009 -0400
@@ -1,3 +1,72 @@
+2009-09-15  Deepak Bhole  <dbhole@redhat.com>
+
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.cc
+	(newMessageOnBus): Handle certain callbacks in a more uniform manner.
+	(postAndWaitForResponse): Lower poll time to 200 us for more
+	responsiveness.
+	(findClass): Accept instance ID which is used for searching classes in
+	specific applet instance classloaders.
+	(getArrayLength): New function. Returns length of an array on Java side.
+	(getSlot): New function. Returns element at requested index in an array.
+	(setSlot): New function. Sets requested index in array to supplied value.
+	(getField): Accept object id.
+	(getStaticField): Fix parameter ordering for consistency.
+	(set): New function. Sets Java side fields to given value.
+	(setStaticField): New function. Sets value of a static field in a Java
+	object.
+	(setField): New function. Sets value of a static field in a class.
+	(createJavaObjectFromVariant): Handle void and null variants. Handle case
+	where object is already created.
+	(call): Use a string to store object id.
+	(newObject): Same.
+	(hasPackage): Accept instance id and pass it on.
+	* plugin/icedteanp/IcedTeaJavaRequestProcessor.h: Relevant changes as
+	needed by the updates to the .cc file.
+	* plugin/icedteanp/IcedTeaNPPlugin.cc
+	(get_scriptable_object): Pass false for the new isArray arg to
+	get_scriptable_java_object.
+	* plugin/icedteanp/IcedTeaPluginRequestProcessor.cc: Pass 0 as the
+	instance id to all findClass calls.
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.cc: Reuse Java object
+	pointers.
+	(IcedTeaScriptableJavaPackageObject::hasProperty): Pass the instance id to
+	findClass.
+	(get_scriptable_java_object): Update code so that Java object pointers can
+	be reused.
+	(IcedTeaScriptableJavaObject::setIsArray): New function. Sets if this object 
+	represents an array.
+	(IcedTeaScriptableJavaObject::getIsArray): New function. Returns if this
+	object represents an array.
+	(IcedTeaScriptableJavaObject::hasMethod): Bypass "array indexes" passed to
+	the method.
+	(IcedTeaScriptableJavaObject::javaResultToNPVariant): Handle void and null
+	values correctly. Handle array objects.
+	(IcedTeaScriptableJavaObject::invoke): Set exceptions in JS engine if one
+	occurred on Java side.
+	(IcedTeaScriptableJavaObject::hasProperty): Handle array length and index
+	properties.
+	(IcedTeaScriptableJavaObject::getProperty): Same.
+	(IcedTeaScriptableJavaObject::setProperty): Add support for setting array
+	index values.
+	* plugin/icedteanp/IcedTeaScriptablePluginObject.h: Changes as
+	necessitated by changes to the .cc file.
+	* plugin/icedteanp/java/sun/applet/JavaConsole.java: Handle changed API in
+	PluginAppletSecurityContext.
+	* plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java
+	(getMatchingMethod): Handle un-castable/deferred casts.
+	(getMatchingConstructor): Same.
+	(getNum): Fix handling for characters.
+	* plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java
+	(associateInstance): New function. Associated a loader with an instance.
+	(getLoaderInfo): New function. Returns loader info in a map.
+	(handleMessage): Look for class in instance specific loaders as well.
+	Handle float/double precision upto 308 (E308 is max for double).
+	* plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+	(AppletEventListener::appletStateChanged): Fix race condition during
+	initialization.
+	(handleMessage): Fix race condition to handle GetJavaObject calls when
+	panel is still being initialized.
+
 2009-08-27  Deepak Bhole <dbhole@redhat.com>
 
 	* plugin/icedteanp/IcedTeaNPPlugin.cc
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.cc	Tue Sep 15 12:47:59 2009 -0400
@@ -37,6 +37,7 @@
 exception statement from your version. */
 
 #include "IcedTeaJavaRequestProcessor.h"
+#include "IcedTeaScriptablePluginObject.h"
 
 /*
  * This class processes LiveConnect requests from JavaScript to Java.
@@ -109,8 +110,6 @@
                     (message_parts->at(4) == "HasField") ||
                     (message_parts->at(4) == "GetStaticFieldID") ||
                     (message_parts->at(4) == "GetFieldID") ||
-                    (message_parts->at(4) == "GetField") ||
-                    (message_parts->at(4) == "GetStaticField") ||
                     (message_parts->at(4) == "GetJavaObject") ||
                     (message_parts->at(4) == "IsInstanceOf"))
 			{
@@ -122,7 +121,10 @@
 			{
 			    result_ready = true; // nothing else to do
 			} else if ((message_parts->at(4) == "CallMethod") ||
-					   (message_parts->at(4) == "CallStaticMethod"))
+					   (message_parts->at(4) == "CallStaticMethod") ||
+					   (message_parts->at(4) == "GetField") ||
+					   (message_parts->at(4) == "GetStaticField") ||
+	                   (message_parts->at(4) == "GetObjectArrayElement"))
 			{
 
 			    if (message_parts->at(5) == "literalreturn")
@@ -140,7 +142,20 @@
 			    }
 
 				result_ready = true;
-			}
+			} else if ((message_parts->at(4) == "GetArrayLength"))
+            {
+			    result->return_identifier = 0; // length is not an "identifier"
+			    result->return_string->append(message_parts->at(5));
+			    result_ready = true;
+            } else if ((message_parts->at(4) == "SetField") ||
+                       (message_parts->at(4) == "SetObjectArrayElement"))
+            {
+
+                // nothing to do
+
+                result->return_identifier = 0;
+                result_ready = true;
+            }
 
 			delete message_parts;
 			return true;
@@ -238,7 +253,7 @@
 			if (g_main_context_pending(NULL))
 				g_main_context_iteration(NULL, false);
 			else
-				usleep(2000);
+				usleep(200);
 		}
 		else
 			break;
@@ -361,9 +376,13 @@
 }
 
 JavaResultData*
-JavaRequestProcessor::findClass(std::string name)
+JavaRequestProcessor::findClass(int plugin_instance_id,
+                                std::string name)
 {
     std::string message = std::string();
+    std::string plugin_instance_id_str = std::string();
+
+    IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
 
 	this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
 	this->reference = IcedTeaPluginUtilities::getReference();
@@ -371,6 +390,8 @@
 	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 
     message.append(" FindClass ");
+    message.append(plugin_instance_id_str);
+    message.append(" ");
     message.append(name);
 
     postAndWaitForResponse(message);
@@ -415,6 +436,72 @@
 }
 
 JavaResultData*
+JavaRequestProcessor::getArrayLength(std::string objectID)
+{
+    std::string message = std::string();
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetArrayLength ");
+    message.append(objectID);
+
+    postAndWaitForResponse(message);
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::getSlot(std::string objectID, std::string index)
+{
+    std::string message = std::string();
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" GetObjectArrayElement ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(index);
+
+    postAndWaitForResponse(message);
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::setSlot(std::string objectID,
+                              std::string index,
+                              NPVariant value)
+{
+    std::string id = std::string();
+    std::string message = std::string();
+
+    createJavaObjectFromVariant(value, &id);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
+
+    message.append(" SetObjectArrayElement ");
+    message.append(objectID);
+    message.append(" ");
+    message.append(index);
+    message.append(" ");
+    message.append(id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
 JavaRequestProcessor::getFieldID(std::string classID, std::string fieldName)
 {
 	JavaResultData* java_result;
@@ -471,6 +558,7 @@
 JavaResultData*
 JavaRequestProcessor::getField(std::string source,
                                std::string classID,
+                               std::string objectID,
                                std::string fieldName)
 {
     JavaResultData* java_result;
@@ -484,7 +572,7 @@
 
     IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
     message.append(" GetField ");
-    message.append(classID);
+    message.append(objectID);
     message.append(" ");
     message.append(java_result->return_string->c_str());
 
@@ -498,7 +586,7 @@
 }
 
 JavaResultData*
-JavaRequestProcessor::getStaticField(std::string classID, std::string source,
+JavaRequestProcessor::getStaticField(std::string source, std::string classID,
                                      std::string fieldName)
 {
     JavaResultData* java_result;
@@ -525,6 +613,70 @@
     return result;
 }
 
+
+JavaResultData*
+JavaRequestProcessor::set(std::string source,
+                          bool isStatic,
+                          std::string classID,
+                          std::string objectID,
+                          std::string fieldName,
+                          NPVariant value)
+{
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+    std::string id = std::string();
+    std::string message = std::string();
+
+    createJavaObjectFromVariant(value, &id);
+
+    java_result = java_request.getFieldID(classID, fieldName);
+
+    this->instance = 0; // context is always 0 (needed for java-side backwards compat.)
+    this->reference = IcedTeaPluginUtilities::getReference();
+
+    IcedTeaPluginUtilities::constructMessagePrefix(0, reference, source, &message);
+
+    if (isStatic)
+    {
+        message.append(" SetStaticField ");
+        message.append(classID);
+    } else
+    {
+        message.append(" SetField ");
+        message.append(objectID);
+    }
+
+    message.append(" ");
+    message.append(java_result->return_string->c_str());
+    message.append(" ");
+    message.append(id);
+
+    postAndWaitForResponse(message);
+
+    IcedTeaPluginUtilities::releaseReference();
+
+    return result;
+}
+
+JavaResultData*
+JavaRequestProcessor::setStaticField(std::string source,
+                                     std::string classID,
+                                     std::string fieldName,
+                                     NPVariant value)
+{
+    return set(source, true, classID, "", fieldName, value);
+}
+
+JavaResultData*
+JavaRequestProcessor::setField(std::string source,
+                               std::string classID,
+                               std::string objectID,
+                               std::string fieldName,
+                               NPVariant value)
+{
+    return set(source, false, classID, objectID, fieldName, value);
+}
+
 JavaResultData*
 JavaRequestProcessor::getMethodID(std::string classID, NPIdentifier methodName,
                                   std::vector<std::string> args)
@@ -601,8 +753,8 @@
     return result;
 }
 
-int
-JavaRequestProcessor::createJavaObjectFromVariant(NPVariant variant)
+void
+JavaRequestProcessor::createJavaObjectFromVariant(NPVariant variant, std::string* id)
 {
 	JavaResultData* java_result;
 
@@ -619,10 +771,14 @@
     if (NPVARIANT_IS_VOID(variant))
     {
     	PLUGIN_DEBUG_1ARG("VOID %d\n", variant);
+    	id->append("0");
+    	return; // no need to go further
     }
     else if (NPVARIANT_IS_NULL(variant))
     {
     	PLUGIN_DEBUG_1ARG("NULL\n", variant);
+    	id->append("0");
+    	return; // no need to go further
     }
     else if (NPVARIANT_IS_BOOLEAN(variant))
     {
@@ -648,7 +804,7 @@
     	className = "java.lang.Double";
 
     	char* valueStr = (char*) malloc(sizeof(char)*1024);
-    	sprintf(valueStr, "%d", NPVARIANT_TO_DOUBLE(variant));
+    	sprintf(valueStr, "%f", NPVARIANT_TO_DOUBLE(variant));
     	stringArg += valueStr;
     	free(valueStr);
     }
@@ -660,17 +816,24 @@
 #else
     	stringArg += NPVARIANT_TO_STRING(variant).UTF8Characters;
 #endif
-    } else {
+    }
+    else if (browser_functions.getproperty())
+    {
+
+    }
+    else
+    {
     	alreadyCreated = true;
     }
 
     if (!alreadyCreated) {
-		java_result = java_request.findClass(className.c_str());
+		java_result = java_request.findClass(0, className.c_str());
 
 		// the result we want is in result_string (assuming there was no error)
 		if (java_result->error_occurred) {
 			printf("Unable to find classid for %s\n", className.c_str());
-			return 0;
+			id->append("0");
+			return;
 		}
 
 		jsObjectClassID.append(*(java_result->return_string));
@@ -685,7 +848,8 @@
 		// the result we want is in result_string (assuming there was no error)
 		if (java_result->error_occurred) {
 			printf("Unable to find string constructor for %s\n", className.c_str());
-			return 0;
+			id->append("0");
+            return;
 		}
 
 		jsObjectConstructorID.append(*(java_result->return_string));
@@ -697,7 +861,8 @@
 
 		if (java_result->error_occurred) {
 			printf("Unable to create requested object\n");
-			return 0;
+			id->append("0");
+            return;
 		}
 
 		// Create the object
@@ -709,21 +874,25 @@
 
         if (java_result->error_occurred) {
             printf("Unable to create requested object\n");
-            return 0;
+            id->append("0");
+            return;
         }
 
 
-		return java_result->return_identifier;
+		id->append(*(java_result->return_string));
+
+	} else {
+	    // Else already created
 
+	    std::string classId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getClassID());
+	    std::string instanceId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getInstanceID());
+
+	    if (instanceId.length() == 0)
+	        id->append(classId.c_str());
+	    else
+	        id->append(instanceId.c_str());
 	}
 
-    std::string classId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getClassID());
-    std::string instanceId = std::string(((IcedTeaScriptableJavaObject*) NPVARIANT_TO_OBJECT(variant))->getInstanceID());
-
-    if (instanceId.length() == 0)
-    	return atoi(classId.c_str());
-    else
-    	return atoi(instanceId.c_str());
 }
 
 JavaResultData*
@@ -766,20 +935,19 @@
     message += " ";
 
 	// First, we need to load the arguments into the java-side table
+    std::string id = std::string();
 	for (int i=0; i < numArgs; i++) {
-		int objectID = createJavaObjectFromVariant(args[i]);
-		if (objectID == 0)
+	    id.clear();
+		createJavaObjectFromVariant(args[i], &id);
+		if (id == "0")
 		{
 			result->error_occurred = true;
 			result->error_msg->append("Unable to create arguments");
 			return result;
 		}
 
-		char* id = (char*) malloc(sizeof(char)*32);
-		sprintf(id, "%d", objectID);
 		message += id;
 		message += " ";
-		free(id);
 	}
 
 	postAndWaitForResponse(message);
@@ -825,20 +993,19 @@
     message += " ";
 
     // First, we need to load the arguments into the java-side table
+    std::string id = std::string();
     for (int i=0; i < argCount; i++) {
-        int objectID = createJavaObjectFromVariant(args[i]);
-        if (objectID == 0)
+        id.clear();
+        createJavaObjectFromVariant(args[i], &id);
+        if (id == "0")
         {
             result->error_occurred = true;
             result->error_msg->append("Unable to create arguments");
             return result;
         }
 
-        char* id = (char*) malloc(sizeof(char)*32);
-        sprintf(id, "%d", objectID);
         message += id;
         message += " ";
-        free(id);
     }
 
     postAndWaitForResponse(message);
@@ -902,11 +1069,14 @@
 }
 
 JavaResultData*
-JavaRequestProcessor::hasPackage(std::string package_name)
+JavaRequestProcessor::hasPackage(int plugin_instance_id,
+                                 std::string package_name)
 {
 	JavaResultData* java_result;
 	JavaRequestProcessor* java_request = new JavaRequestProcessor();
 	std::string message = std::string();
+	std::string plugin_instance_id_str = std::string();
+	IcedTeaPluginUtilities::itoa(plugin_instance_id, &plugin_instance_id_str);
 
 	java_result = java_request->newString(package_name);
 
@@ -915,6 +1085,8 @@
 
 	IcedTeaPluginUtilities::constructMessagePrefix(0, reference, &message);
 	message.append(" HasPackage ");
+    message.append(plugin_instance_id_str);
+    message.append(" ");
 	message.append(java_result->return_string->c_str());
 
 	postAndWaitForResponse(message);
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.h	Tue Sep 15 12:47:59 2009 -0400
@@ -45,7 +45,6 @@
 
 #include "IcedTeaNPPlugin.h"
 #include "IcedTeaPluginUtils.h"
-#include "IcedTeaScriptablePluginObject.h"
 
 #define REQUESTTIMEOUT 120
 
@@ -105,13 +104,21 @@
     	void postAndWaitForResponse(std::string message);
 
     	/* Creates a argument on java-side with appropriate type */
-    	int createJavaObjectFromVariant(NPVariant variant);
+    	void createJavaObjectFromVariant(NPVariant variant, std::string* id);
 
     	// Call a method, static or otherwise, depending on supplied arg
         JavaResultData* call(std::string source, bool isStatic,
                              std::string objectID, std::string methodName,
                              const NPVariant* args, int numArgs);
 
+        // Set a static/non-static field to given value
+        JavaResultData* set(std::string source,
+                            bool isStatic,
+                            std::string classID,
+                            std::string objectID,
+                            std::string fieldName,
+                            NPVariant value);
+
         /* Resets the results */
         void resetResult();
 
@@ -135,6 +142,7 @@
     	/* Returns the field object */
         JavaResultData* getField(std::string source,
                                  std::string classID,
+                                 std::string objectID,
                                  std::string fieldName);
 
         /* Returns the static field object */
@@ -142,6 +150,19 @@
                                        std::string classID,
                                        std::string fieldName);
 
+        /* Sets the field object */
+        JavaResultData* setField(std::string source,
+                                 std::string classID,
+                                 std::string objectID,
+                                 std::string fieldName,
+                                 NPVariant value);
+
+        /* Sets the static field object */
+        JavaResultData* setStaticField(std::string source,
+                                       std::string classID,
+                                       std::string fieldName,
+                                       NPVariant value);
+
         /* Returns the field id */
         JavaResultData* getFieldID(std::string classID, std::string fieldName);
 
@@ -182,7 +203,8 @@
                                   std::vector<std::string> args);
 
     	/* Returns the class ID */
-    	JavaResultData* findClass(std::string name);
+    	JavaResultData* findClass(int plugin_instance_id,
+                                  std::string name);
 
     	/* Returns the type class name */
     	JavaResultData* getClassName(std::string objectID);
@@ -190,11 +212,23 @@
     	/* Returns the type class id */
     	JavaResultData* getClassID(std::string objectID);
 
+    	/* Returns the length of the array object. -1 if not found */
+    	JavaResultData* getArrayLength(std::string objectID);
+
+    	/* Returns the item at the given index for the array */
+    	JavaResultData* getSlot(std::string objectID, std::string index);
+
+        /* Sets the item at the given index to the given value */
+        JavaResultData* setSlot(std::string objectID,
+                                std::string index,
+                                NPVariant value);
+
     	/* Creates a new string in the Java store */
     	JavaResultData* newString(std::string str);
 
     	/* Check if package exists */
-    	JavaResultData* hasPackage(std::string package_name);
+    	JavaResultData* hasPackage(int plugin_instance_id,
+                                   std::string package_name);
 
         /* Check if method exists */
         JavaResultData* hasMethod(std::string classID, std::string method_name);
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaNPPlugin.cc	Tue Sep 15 12:47:59 2009 -0400
@@ -399,7 +399,7 @@
   documentbase = NULL;
 
   // store an identifier for this plugin
-  PLUGIN_DEBUG_2ARG("Mapping id instance_counter and instance %p", instance_counter, instance);
+  PLUGIN_DEBUG_2ARG("Mapping id %d and instance %p\n", instance_counter, instance);
   g_hash_table_insert(instance_to_id_map, instance, GINT_TO_POINTER(instance_counter));
   g_hash_table_insert(id_to_instance_map, GINT_TO_POINTER(instance_counter), instance);
   instance_counter++;
@@ -1285,8 +1285,10 @@
 
 int get_id_from_instance(NPP instance)
 {
-    return GPOINTER_TO_INT(g_hash_table_lookup(instance_to_id_map,
-                                                   instance));
+    int id = GPOINTER_TO_INT(g_hash_table_lookup(instance_to_id_map,
+                                                       instance));
+    PLUGIN_DEBUG_2ARG("Returning id %d for instance %p\n", id, instance);
+    return id;
 }
 
 void decode_url(const gchar* url, gchar** decoded_url)
@@ -2242,7 +2244,7 @@
 
         applet_class_id.append(*(java_result->return_string));
 
-        obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, applet_class_id, instance_id);
+        obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, applet_class_id, instance_id, false);
 
     } else
     {
--- a/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaPluginRequestProcessor.cc	Tue Sep 15 12:47:59 2009 -0400
@@ -38,6 +38,7 @@
 
 #include <typeinfo>
 
+#include "IcedTeaScriptablePluginObject.h"
 #include "IcedTeaNPPlugin.h"
 #include "IcedTeaPluginRequestProcessor.h"
 
@@ -277,23 +278,23 @@
     std::string char_class_id = std::string();
     std::string string_class_id = std::string();
 
-    java_result = java_request.findClass("java.lang.Number");
+    java_result = java_request.findClass(0, "java.lang.Number");
     CHECK_JAVA_RESULT(java_result);
     number_class_id.append(*(java_result->return_string));
 
-    java_result = java_request.findClass("java.lang.Boolean");
+    java_result = java_request.findClass(0, "java.lang.Boolean");
     CHECK_JAVA_RESULT(java_result);
     boolean_class_id.append(*(java_result->return_string));
 
-    java_result = java_request.findClass("java.lang.Byte");
+    java_result = java_request.findClass(0, "java.lang.Byte");
     CHECK_JAVA_RESULT(java_result);
     byte_class_id.append(*(java_result->return_string));
 
-    java_result = java_request.findClass("java.lang.Character");
+    java_result = java_request.findClass(0, "java.lang.Character");
     CHECK_JAVA_RESULT(java_result);
     char_class_id.append(*(java_result->return_string));
 
-    java_result = java_request.findClass("java.lang.String");
+    java_result = java_request.findClass(0, "java.lang.String");
     CHECK_JAVA_RESULT(java_result);
     string_class_id.append(*(java_result->return_string));
 
@@ -423,7 +424,7 @@
             CHECK_JAVA_RESULT(java_result);
             class_id.append(*(java_result->return_string));
 
-            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, class_id, id);
+            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(instance, class_id, id, false);
 
             OBJECT_TO_NPVARIANT(obj, *variant);
 
@@ -712,7 +713,7 @@
 
     internal_req_ref_counter--;
 
-    java_result = java_request.findClass("netscape.javascript.JSObject");
+    java_result = java_request.findClass(0, "netscape.javascript.JSObject");
 
     // the result we want is in result_string (assuming there was no error)
     if (java_result->error_occurred)
@@ -872,7 +873,7 @@
         else
             value_str = "false";
 
-        java_result = java_request.findClass("java.lang.Boolean");
+        java_result = java_request.findClass(0, "java.lang.Boolean");
         CHECK_JAVA_RESULT(java_result);
         boolean_classid.append(*(java_result->return_string));
 
@@ -901,7 +902,7 @@
         std::string value_str = std::string();
         IcedTeaPluginUtilities::itoa(NPVARIANT_TO_INT32(variant), &value_str);
 
-        java_result = java_request.findClass("java.lang.Integer");
+        java_result = java_request.findClass(0, "java.lang.Integer");
         CHECK_JAVA_RESULT(java_result);
         integer_classid.append(*(java_result->return_string));
 
@@ -930,7 +931,7 @@
         std::string value_str = std::string();
         IcedTeaPluginUtilities::itoa(NPVARIANT_TO_DOUBLE(variant), &value_str);
 
-        java_result = java_request.findClass("java.lang.Double");
+        java_result = java_request.findClass(0, "java.lang.Double");
         CHECK_JAVA_RESULT(java_result);
         double_classid.append(*(java_result->return_string));
 
@@ -963,7 +964,6 @@
         result->append(*(java_result->return_string));
     } else {
 
-
         // Else it is a complex object
         if (typeid(IcedTeaScriptableJavaObject*) == typeid(NPVARIANT_TO_OBJECT(variant)))
         {
@@ -979,7 +979,7 @@
             printf("Got NPObject %p\n", NPVARIANT_TO_OBJECT(variant));
             IcedTeaPluginUtilities::JSIDToString(NPVARIANT_TO_OBJECT(variant), &value_str);
 
-            java_result = java_request.findClass("netscape.javascript.JSObject");
+            java_result = java_request.findClass(0, "netscape.javascript.JSObject");
             CHECK_JAVA_RESULT(java_result);
             jsobject_classid.append(*(java_result->return_string));
 
--- a/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaScriptablePluginObject.cc	Tue Sep 15 12:47:59 2009 -0400
@@ -168,8 +168,11 @@
 	return scriptable_object;
 }
 
+std::map<std::string, NPObject*>* IcedTeaScriptableJavaPackageObject::object_map = new std::map<std::string, NPObject*>();
+
 IcedTeaScriptableJavaPackageObject::IcedTeaScriptableJavaPackageObject(NPP instance)
 {
+    PLUGIN_DEBUG_0ARG("Constructing new scriptable java package object\n");
 	this->instance = instance;
 	this->package_name = new std::string();
 }
@@ -234,26 +237,34 @@
 	bool hasProperty = false;
 	JavaResultData* java_result;
 	JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+    int plugin_instance_id = get_id_from_instance(instance);
 
-	printf("\"%s\"\n", ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().c_str());
+	PLUGIN_DEBUG_1ARG("Object package name: \"%s\"\n", ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().c_str());
+
+	// "^java" is always a package
+	if (((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().length() == 0 &&
+	    (  !strcmp(browser_functions.utf8fromidentifier(name), "java") ||
+	       !strcmp(browser_functions.utf8fromidentifier(name), "javax")))
+	{
+	    return true;
+	}
 
 	std::string property_name = ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName();
 	if (property_name.length() > 0)
 	    property_name += ".";
 	property_name += browser_functions.utf8fromidentifier(name);
 
-	printf("\"%s\" \"%s\" \"%s\" = \"%s\"\n",
-	          ((IcedTeaScriptableJavaPackageObject*) npobj)->getPackageName().c_str(), ".",
-	          browser_functions.utf8fromidentifier(name), property_name.c_str());
+	PLUGIN_DEBUG_1ARG("Looking for name \"%s\"\n", property_name.c_str());
 
-	java_result = java_request->hasPackage(property_name);
+	java_result = java_request->hasPackage(plugin_instance_id, property_name);
 
 	if (!java_result->error_occurred && java_result->return_identifier != 0) hasProperty = true;
 
 	// No such package. Do we have a class with that name?
 	if (!hasProperty)
 	{
-		java_result = java_request->findClass(property_name);
+		java_result = java_request->findClass(plugin_instance_id, property_name);
 	}
 
 	if (java_result->return_identifier != 0) hasProperty = true;
@@ -269,6 +280,9 @@
 
 	PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaPackageObject::getProperty %s\n", browser_functions.utf8fromidentifier(name));
 
+	if (!browser_functions.utf8fromidentifier(name))
+	    return false;
+
 	bool isPropertyClass = false;
 	JavaResultData* java_result;
 	JavaRequestProcessor java_request = JavaRequestProcessor();
@@ -278,7 +292,7 @@
 	    property_name += ".";
 	property_name += browser_functions.utf8fromidentifier(name);
 
-	java_result = java_request.findClass(property_name);
+	java_result = java_request.findClass(0, property_name);
 	isPropertyClass = (java_result->return_identifier == 0);
 
 	//NPIdentifier property = browser_functions.getstringidentifier(property_name.c_str());
@@ -297,7 +311,7 @@
 		PLUGIN_DEBUG_0ARG("Returning Java object\n");
 		obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
 		                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
-		                *(java_result->return_string), "0");
+		                *(java_result->return_string), "0", false);
 	}
 
 	OBJECT_TO_NPVARIANT(obj, *result);
@@ -308,7 +322,7 @@
 bool
 IcedTeaScriptableJavaPackageObject::setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
 {
-	printf ("** Unimplemented: IcedTeaScriptableJavaPackageObject::setProperty %p\n", npobj);
+	// Can't be going around setting properties on namespaces.. that's madness!
 	return false;
 }
 
@@ -337,14 +351,33 @@
 NPObject*
 allocate_scriptable_java_object(NPP npp, NPClass *aClass)
 {
-    PLUGIN_DEBUG_0ARG("Allocating new scriptable Java Package object\n");
+    PLUGIN_DEBUG_0ARG("Allocating new scriptable Java object\n");
     return new IcedTeaScriptableJavaObject(npp);
 }
 
 NPObject*
-IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(NPP instance, std::string class_id, std::string instance_id)
+IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(NPP instance,
+                                    std::string class_id,
+                                    std::string instance_id,
+                                    bool isArray)
 {
-	NPObject* scriptable_object;
+    NPObject* scriptable_object;
+
+    std::string obj_key = std::string();
+    obj_key += class_id;
+    obj_key += ":";
+    obj_key += instance_id;
+
+    std::map<std::string, NPObject*>::iterator iterator = object_map->find(obj_key);
+    PLUGIN_DEBUG_1ARG("get_scriptable_java_object searching for %s...\n", obj_key.c_str());
+
+    if (iterator != object_map->end())
+    {
+        scriptable_object = object_map->find(obj_key)->second;
+        PLUGIN_DEBUG_2ARG("Found existing match for key %s. Returning %p\n", obj_key.c_str(), scriptable_object);
+        browser_functions.retainobject(scriptable_object);
+        return scriptable_object;
+    }
 
 	NPClass* np_class = new NPClass();
 	np_class->structVersion = NP_CLASS_STRUCT_VERSION;
@@ -362,15 +395,20 @@
 	np_class->construct = IcedTeaScriptableJavaObject::construct;
 
 	scriptable_object = browser_functions.createobject(instance, np_class);
-	PLUGIN_DEBUG_2ARG("Returning new scriptable class: %p from instance %p\n", scriptable_object, instance);
+	browser_functions.retainobject(scriptable_object);
+	PLUGIN_DEBUG_3ARG("Constructing new Java Object with classid=%s, instanceid=%s and isArray=%d\n", class_id.c_str(), instance_id.c_str(), isArray);
 
 	((IcedTeaScriptableJavaObject*) scriptable_object)->setClassIdentifier(class_id);
+    ((IcedTeaScriptableJavaObject*) scriptable_object)->setIsArray(isArray);
 
 	if (instance_id != "0")
 	    ((IcedTeaScriptableJavaObject*) scriptable_object)->setInstanceIdentifier(instance_id);
 
 	IcedTeaPluginUtilities::storeInstanceID(scriptable_object, instance);
 
+	object_map->insert(std::make_pair(obj_key, scriptable_object));
+
+	PLUGIN_DEBUG_2ARG("Inserting into object_map key %s->%p\n", obj_key.c_str(), scriptable_object);
 	return scriptable_object;
 }
 
@@ -400,6 +438,12 @@
 }
 
 void
+IcedTeaScriptableJavaObject::setIsArray(bool isArray)
+{
+    this->isObjectArray = isArray;
+}
+
+void
 IcedTeaScriptableJavaObject::deAllocate(NPObject *npobj)
 {
 	printf ("** Unimplemented: IcedTeaScriptableJavaObject::deAllocate %p\n", npobj);
@@ -414,69 +458,38 @@
 bool
 IcedTeaScriptableJavaObject::hasMethod(NPObject *npobj, NPIdentifier name)
 {
+    PLUGIN_DEBUG_2ARG("IcedTeaScriptableJavaObject::hasMethod %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
     bool hasMethod = false;
-    JavaResultData* java_result;
-    JavaRequestProcessor* java_request = new JavaRequestProcessor();
+
+    // If object is an array and requested "method" may be a number, check for it first
+    if ( !((IcedTeaScriptableJavaObject*) npobj)->isArray()  ||
+         (browser_functions.intfromidentifier(name) < 0))
+    {
+
+        if (!browser_functions.utf8fromidentifier(name))
+            return false;
 
-    std::string classId = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
-    std::string methodName = browser_functions.utf8fromidentifier(name);
+        JavaResultData* java_result;
+        JavaRequestProcessor java_request = JavaRequestProcessor();
+
+        std::string classId = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
+        std::string methodName = browser_functions.utf8fromidentifier(name);
 
-    java_result = java_request->hasMethod(classId, methodName);
-    hasMethod = java_result->return_identifier != 0;
+        java_result = java_request.hasMethod(classId, methodName);
+        hasMethod = java_result->return_identifier != 0;
+    }
 
-    delete java_request;
-
+    PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaObject::hasMethod returning %d\n", hasMethod);
     return hasMethod;
 }
 
 bool
-IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
-			uint32_t argCount,NPVariant *result)
+IcedTeaScriptableJavaObject::javaResultToNPVariant(NPObject *npobj,
+                                                   JavaResultData* java_result,
+                                                   NPVariant* variant)
 {
-    NPUTF8* method_name = browser_functions.utf8fromidentifier(name);
-
-    // Extract arg type array
-    printf ("IcedTeaScriptableJavaObject::invoke %s. Args follow.\n", method_name);
-    for (int i=0; i < argCount; i++)
-    {
-        IcedTeaPluginUtilities::printNPVariant(args[i]);
-    }
-
-    JavaResultData* java_result;
     JavaRequestProcessor java_request = JavaRequestProcessor();
 
-    NPObject* obj;
-    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
-    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
-    std::string callee;
-    std::string source;
-
-    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
-
-    if (instance_id.length() == 0) // Static
-    {
-        printf("Calling static method\n");
-        callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
-        java_result = java_request.callStaticMethod(
-                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
-                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
-    } else
-    {
-        printf("Calling method normally\n");
-        callee = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
-        java_result = java_request.callMethod(
-                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
-                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
-    }
-
-    if (java_result->error_occurred)
-    {
-        // error message must be allocated on heap
-        char* error_msg = (char*) malloc(java_result->error_msg->length()*sizeof(char));
-        browser_functions.setexception(npobj, error_msg);
-        return false;
-    }
-
     if (java_result->return_identifier == 0)
     {
         // VOID/BOOLEAN/NUMBER
@@ -484,15 +497,19 @@
         if (*(java_result->return_string) == "void")
         {
             PLUGIN_DEBUG_0ARG("Method call returned void\n");
-            VOID_TO_NPVARIANT(*result);
-        } else if (*(java_result->return_string) == "true")
+            VOID_TO_NPVARIANT(*variant);
+        } else if (*(java_result->return_string) == "null")
+        {
+            PLUGIN_DEBUG_0ARG("Method call returned null\n");
+            NULL_TO_NPVARIANT(*variant);
+        }else if (*(java_result->return_string) == "true")
         {
             PLUGIN_DEBUG_0ARG("Method call returned a boolean (true)\n");
-            BOOLEAN_TO_NPVARIANT(true, *result);
+            BOOLEAN_TO_NPVARIANT(true, *variant);
         } else if (*(java_result->return_string) == "false")
         {
             PLUGIN_DEBUG_0ARG("Method call returned a boolean (false)\n");
-            BOOLEAN_TO_NPVARIANT(false, *result);
+            BOOLEAN_TO_NPVARIANT(false, *variant);
         } else
         {
             double d = strtod(java_result->return_string->c_str(), NULL);
@@ -503,12 +520,12 @@
                 d > 0x7fffffffL)
             {
                 PLUGIN_DEBUG_1ARG("Method call returned a double %f\n", d);
-                DOUBLE_TO_NPVARIANT(d, *result);
+                DOUBLE_TO_NPVARIANT(d, *variant);
             } else
             {
                 int32_t i = (int32_t) d;
                 PLUGIN_DEBUG_1ARG("Method call returned an int %d\n", i);
-                INT32_TO_NPVARIANT(i, *result);
+                INT32_TO_NPVARIANT(i, *variant);
             }
         }
     } else {
@@ -542,8 +559,8 @@
             NPUTF8* return_str = (NPUTF8*) malloc(sizeof(NPUTF8)*java_result->return_string->size() + 1);
             strcpy(return_str, java_result->return_string->c_str());
 
-            PLUGIN_DEBUG_1ARG("Method call returned a string %s\n", return_str);
-            STRINGZ_TO_NPVARIANT(return_str, *result);
+            PLUGIN_DEBUG_1ARG("Method call returned a string: \"%s\"\n", return_str);
+            STRINGZ_TO_NPVARIANT(return_str, *variant);
 
             // delete string from java side, as it is no longer needed
             java_request.deleteReference(return_obj_instance_id);
@@ -551,7 +568,7 @@
 
             // Else this is a regular class. Reference the class object so
             // we can construct an NPObject with it and the instance
-            java_result = java_request.findClass(return_obj_class_name);
+            java_result = java_request.getClassID(return_obj_instance_id);
 
             if (java_result->error_occurred)
             {
@@ -561,16 +578,73 @@
             return_obj_class_id.append(*(java_result->return_string));
 
             NPObject* obj;
-            obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
-                            IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
-                            return_obj_class_id, return_obj_instance_id);
 
-            OBJECT_TO_NPVARIANT(obj, *result);
+            if (return_obj_class_name.find('[') == 0) // array
+                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                                return_obj_class_id, return_obj_instance_id, true);
+            else
+                obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
+                                                IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
+                                                return_obj_class_id, return_obj_instance_id, false);
+
+            OBJECT_TO_NPVARIANT(obj, *variant);
         }
     }
 
-    PLUGIN_DEBUG_0ARG("IcedTeaScriptableJavaObject::invoke returning.\n");
-	return true;
+    return true;
+}
+
+bool
+IcedTeaScriptableJavaObject::invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+			uint32_t argCount, NPVariant *result)
+{
+    NPUTF8* method_name = browser_functions.utf8fromidentifier(name);
+
+    // Extract arg type array
+    PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaObject::invoke %s. Args follow.\n", method_name);
+    for (int i=0; i < argCount; i++)
+    {
+        IcedTeaPluginUtilities::printNPVariant(args[i]);
+    }
+
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+    std::string callee;
+    std::string source;
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
+    if (instance_id.length() == 0) // Static
+    {
+        PLUGIN_DEBUG_0ARG("Calling static method\n");
+        callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+        java_result = java_request.callStaticMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
+    } else
+    {
+        PLUGIN_DEBUG_0ARG("Calling method normally\n");
+        callee = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+        java_result = java_request.callMethod(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        callee, browser_functions.utf8fromidentifier(name), args, argCount);
+    }
+
+    if (java_result->error_occurred)
+    {
+        // error message must be allocated on heap
+        char* error_msg = (char*) malloc(java_result->error_msg->length()*sizeof(char));
+        browser_functions.setexception(npobj, error_msg);
+        return false;
+    }
+
+    PLUGIN_DEBUG_0ARG("IcedTeaScriptableJavaObject::invoke converting and returning.\n");
+    return IcedTeaScriptableJavaObject::javaResultToNPVariant(npobj, java_result, result);
 }
 
 bool
@@ -584,28 +658,47 @@
 bool
 IcedTeaScriptableJavaObject::hasProperty(NPObject *npobj, NPIdentifier name)
 {
-    PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaObject::hasProperty %s\n", browser_functions.utf8fromidentifier(name));
+    PLUGIN_DEBUG_2ARG("IcedTeaScriptableJavaObject::hasProperty %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+    bool hasProperty = false;
 
-	bool hasProperty = false;
-	JavaResultData* java_result;
-	JavaRequestProcessor* java_request = new JavaRequestProcessor();
+    // If it is an array, only length and indexes are valid
+    if (((IcedTeaScriptableJavaObject*) npobj)->isArray())
+    {
+        if (browser_functions.intfromidentifier(name) >= 0 ||
+            !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+            hasProperty = true;
+
+    } else
+    {
+
+        if (!browser_functions.utf8fromidentifier(name))
+            return false;
 
-	std::string class_id = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
-	std::string fieldName = browser_functions.utf8fromidentifier(name);
+        if (!strcmp(browser_functions.utf8fromidentifier(name), "Packages"))
+        {
+            hasProperty = true;
+        } else {
 
-    java_result = java_request->hasField(class_id, fieldName);
+            JavaResultData* java_result;
+            JavaRequestProcessor java_request = JavaRequestProcessor();
 
-	hasProperty = java_result->return_identifier != 0;
+            std::string class_id = std::string(((IcedTeaScriptableJavaObject*) npobj)->getClassID());
+            std::string fieldName = browser_functions.utf8fromidentifier(name);
+
+            java_result = java_request.hasField(class_id, fieldName);
 
-	delete java_request;
+            hasProperty = java_result->return_identifier != 0;
+        }
+    }
 
+	PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaObject::hasProperty returning %d\n", hasProperty);
 	return hasProperty;
 }
 
 bool
 IcedTeaScriptableJavaObject::getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
 {
-    PLUGIN_DEBUG_1ARG("IcedTeaScriptableJavaObject::getProperty %s\n", browser_functions.utf8fromidentifier(name));
+    PLUGIN_DEBUG_2ARG("IcedTeaScriptableJavaObject::getProperty %s (ival=%d)\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
 
     bool isPropertyClass = false;
     JavaResultData* java_result;
@@ -614,37 +707,147 @@
     NPObject* obj;
     std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
     std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
-    std::string callee = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+    NPP instance = ((IcedTeaScriptableJavaObject*) npobj)->getInstance();
+
+    if (instance_id.length() > 0) // Could be an array or a simple object
+    {
+        // If array and requesting length
+        if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+             browser_functions.utf8fromidentifier(name) &&
+             !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+        {
+            java_result = java_request.getArrayLength(instance_id);
+        } else if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+                    browser_functions.intfromidentifier(name) >= 0) // else if array and requesting index
+        {
+
+            java_result = java_request.getArrayLength(instance_id);
+            if (java_result->error_occurred)
+            {
+                printf("ERROR: Couldn't fetch array length\n");
+                return false;
+            }
+
+            int length = atoi(java_result->return_string->c_str());
+
+            // Access beyond size?
+            if (browser_functions.intfromidentifier(name) >= length)
+            {
+                NULL_TO_NPVARIANT(*result);
+                return true;
+            }
 
-    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
-    java_result = java_request.getField(
-                    IcedTeaPluginUtilities::getSourceFromInstance(instance),
-                    callee, browser_functions.utf8fromidentifier(name));
+            std::string index = std::string();
+            IcedTeaPluginUtilities::itoa(browser_functions.intfromidentifier(name), &index);
+            java_result = java_request.getSlot(instance_id, index);
+
+        } else // Everything else
+        {
+            if (!browser_functions.utf8fromidentifier(name))
+                return false;
 
-    std::string object_id = *(java_result->return_string);
+            if (!strcmp(browser_functions.utf8fromidentifier(name), "Packages"))
+            {
+                NPObject* pkgObject = IcedTeaScriptablePluginObject::get_scriptable_java_package_object(instance, "");
+                OBJECT_TO_NPVARIANT(pkgObject, *result);
+                return true;
+            }
 
-    // get the class of this object
-    java_result = java_request.getObjectClass(object_id);
+            java_result = java_request.getField(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        class_id, instance_id, browser_functions.utf8fromidentifier(name));
+        }
+    }
+    else
+    {
+        if (!browser_functions.utf8fromidentifier(name))
+            return true;
+
+        java_result = java_request.getStaticField(
+                                IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                                class_id, browser_functions.utf8fromidentifier(name));
+    }
 
     if (java_result->error_occurred)
     {
         return false;
     }
 
-    obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
-                    IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
-                    *(java_result->return_string), object_id);
+    PLUGIN_DEBUG_0ARG("IcedTeaScriptableJavaObject::getProperty converting and returning.\n");
+    return IcedTeaScriptableJavaObject::javaResultToNPVariant(npobj, java_result, result);
 
-    OBJECT_TO_NPVARIANT(obj, *result);
-
-    return true;
 }
 
 bool
 IcedTeaScriptableJavaObject::setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
 {
-	printf ("** Unimplemented: IcedTeaScriptableJavaObject::setProperty %p\n", npobj);
-	return false;
+    PLUGIN_DEBUG_2ARG("IcedTeaScriptableJavaObject::setProperty %s (ival=%d) to:\n", browser_functions.utf8fromidentifier(name), browser_functions.intfromidentifier(name));
+    IcedTeaPluginUtilities::printNPVariant(*value);
+
+    bool isPropertyClass = false;
+    JavaResultData* java_result;
+    JavaRequestProcessor java_request = JavaRequestProcessor();
+
+    NPObject* obj;
+    std::string instance_id = ((IcedTeaScriptableJavaObject*) npobj)->getInstanceID();
+    std::string class_id = ((IcedTeaScriptableJavaObject*) npobj)->getClassID();
+
+    NPP instance = IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj);
+
+    if (instance_id.length() > 0) // Could be an array or a simple object
+    {
+        // If array
+        if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+             browser_functions.utf8fromidentifier(name) &&
+             !strcmp(browser_functions.utf8fromidentifier(name), "length"))
+        {
+            printf("ERROR: Array length is not a modifiable property\n");
+            return false;
+        } else if ( ((IcedTeaScriptableJavaObject*) npobj)->isArray() &&
+                    browser_functions.intfromidentifier(name) >= 0) // else if array and requesting index
+        {
+
+            java_result = java_request.getArrayLength(instance_id);
+            if (java_result->error_occurred)
+            {
+                printf("ERROR: Couldn't fetch array length\n");
+                return false;
+            }
+
+            int length = atoi(java_result->return_string->c_str());
+
+            // Access beyond size?
+            if (browser_functions.intfromidentifier(name) >= length)
+            {
+                return true;
+            }
+
+            std::string index = std::string();
+            IcedTeaPluginUtilities::itoa(browser_functions.intfromidentifier(name), &index);
+            java_result = java_request.setSlot(instance_id, index, *value);
+
+        } else // Everything else
+        {
+
+            java_result = java_request.setField(
+                        IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                        class_id, instance_id, browser_functions.utf8fromidentifier(name), *value);
+        }
+    }
+    else
+    {
+        java_result = java_request.setStaticField(
+                                IcedTeaPluginUtilities::getSourceFromInstance(instance),
+                                class_id, browser_functions.utf8fromidentifier(name), *value);
+    }
+
+    if (java_result->error_occurred)
+    {
+        return false;
+    }
+
+    PLUGIN_DEBUG_0ARG("IcedTeaScriptableJavaObject::setProperty returning.\n");
+    return true;
 }
 
 bool
@@ -704,7 +907,7 @@
 
     obj = IcedTeaScriptableJavaPackageObject::get_scriptable_java_object(
                                 IcedTeaPluginUtilities::getInstanceFromMemberPtr(npobj),
-                                return_obj_class_id, return_obj_instance_id);
+                                return_obj_class_id, return_obj_instance_id, false);
 
     OBJECT_TO_NPVARIANT(obj, *result);
 
--- a/plugin/icedteanp/IcedTeaScriptablePluginObject.h	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/IcedTeaScriptablePluginObject.h	Tue Sep 15 12:47:59 2009 -0400
@@ -94,7 +94,7 @@
         static NPObject* get_scriptable_java_package_object(NPP instance, const NPUTF8* name);
 };
 
-NPObject* voidallocate_scriptable_jp_object(NPP npp, NPClass *aClass);
+NPObject* allocate_scriptable_jp_object(NPP npp, NPClass *aClass);
 
 class IcedTeaScriptableJavaPackageObject: public NPObject
 {
@@ -103,6 +103,8 @@
     	NPP instance;
     	std::string* package_name;
 
+        static std::map<std::string, NPObject*>* object_map;
+
     public:
     	IcedTeaScriptableJavaPackageObject(NPP instance);
 
@@ -140,7 +142,10 @@
         static bool construct(NPObject *npobj, const NPVariant *args,
                 uint32_t argCount, NPVariant *result);
 
-        static NPObject* get_scriptable_java_object(NPP instance, std::string class_id, std::string instance_id);
+        static NPObject* get_scriptable_java_object(NPP instance,
+                                                    std::string class_id,
+                                                    std::string instance_id,
+                                                    bool isArray);
 };
 
 class IcedTeaScriptableJavaObject: public NPObject
@@ -148,9 +153,14 @@
 
     private:
     	NPP instance;
+    	bool isObjectArray;
     	std::string* class_id;
     	std::string* instance_id;
 
+    	static bool javaResultToNPVariant(NPObject *npobj,
+                                          JavaResultData* java_result,
+                                          NPVariant* variant);
+
     public:
     	IcedTeaScriptableJavaObject(NPP instance);
 
@@ -160,10 +170,16 @@
 
     	void setInstanceIdentifier(std::string instance_id);
 
+    	void setIsArray(bool isArray);
+
     	std::string getClassID() { return *class_id; }
 
     	std::string getInstanceID() { return *instance_id; }
 
+    	NPP getInstance() { return instance; }
+
+    	bool isArray() { return isObjectArray; }
+
         static void deAllocate(NPObject *npobj);
 
         static void invalidate(NPObject *npobj);
--- a/plugin/icedteanp/java/sun/applet/JavaConsole.java	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/JavaConsole.java	Tue Sep 15 12:47:59 2009 -0400
@@ -261,11 +261,11 @@
     private void printClassLoaders() {
         System.out.println(" ----");
         System.out.println("Available Classloaders: ");
-        Set<ClassLoader> loaders = PluginAppletSecurityContext.classLoaders.keySet();
-        for (ClassLoader loader: loaders) {
-            System.out.println(loader.getClass().getName() + "\n"
+        Set<String> loaders = PluginAppletSecurityContext.getLoaderInfo().keySet();
+        for (String loader: loaders) {
+            System.out.println(loader + "\n"
                     + "  codebase = " 
-                    + PluginAppletSecurityContext.classLoaders.get(loader));
+                    + PluginAppletSecurityContext.getLoaderInfo().get(loader));
         }
         System.out.println(" ----");
     }
--- a/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/MethodOverloadResolver.java	Tue Sep 15 12:47:59 2009 -0400
@@ -195,6 +195,9 @@
                 Object[] costAndCastedObj = getCostAndCastedObject(
                         suppliedParam, paramTypeClass);
                 methodCost += (Integer) costAndCastedObj[0];
+                
+                if ((Integer) costAndCastedObj[0] < 0) break;
+                
                 Object castedObj = paramTypeClass.isPrimitive() ? costAndCastedObj[1]
                         : paramTypeClass.cast(costAndCastedObj[1]);
                 methodAndArgs[i + 1] = castedObj;
@@ -256,6 +259,9 @@
                 Object[] costAndCastedObj = getCostAndCastedObject(
                         suppliedParam, paramTypeClass);
                 constructorCost += (Integer) costAndCastedObj[0];
+                
+                if ((Integer) costAndCastedObj[0] < 0) break;
+                
                 Object castedObj = paramTypeClass.isPrimitive() ? costAndCastedObj[1]
                         : paramTypeClass.cast(costAndCastedObj[1]);
                 constructorAndArgs[i + 1] = castedObj;
@@ -284,7 +290,7 @@
         return ret;
     }
 
-    private static Object[] getCostAndCastedObject(Object suppliedParam, Class paramTypeClass) {
+    public static Object[] getCostAndCastedObject(Object suppliedParam, Class paramTypeClass) {
         
         Object[] ret = new Object[2];
         Integer cost = new Integer(0);
@@ -341,7 +347,7 @@
             castedObj = (JSObject) suppliedParam; // FIXME: Arrays not yet handled
         } else {
             cost = Integer.MIN_VALUE; // Not allowed
-            castedObj = null;
+            castedObj = suppliedParam;
         }
         
         ret[0] = cost;
@@ -459,8 +465,8 @@
         }
 
         if (c.equals(java.lang.Character.class) ||
-                c.equals(java.lang.Character.TYPE)) {
-            return s.charAt(0);
+            c.equals(java.lang.Character.TYPE)) {
+            return (char) n.intValue();
         }
 
         return n;
--- a/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletSecurityContext.java	Tue Sep 15 12:47:59 2009 -0400
@@ -53,11 +53,11 @@
 import java.security.Permissions;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
+import java.text.DecimalFormat;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.List;
-
-import sun.reflect.generics.repository.MethodRepository;
+import java.util.Map;
 
 import net.sourceforge.jnlp.runtime.JNLPRuntime;
 import netscape.javascript.JSObjectCreatePermission;
@@ -233,7 +233,8 @@
 
 public class PluginAppletSecurityContext {
 	
-	public static Hashtable<ClassLoader, URL> classLoaders = new Hashtable<ClassLoader, URL>();
+	private static Hashtable<ClassLoader, URL> classLoaders = new Hashtable<ClassLoader, URL>();
+	private static Hashtable<Integer, ClassLoader> instanceClassLoaders = new Hashtable<Integer, ClassLoader>();
 
 	// FIXME: make private
 	public PluginObjectStore store = new PluginObjectStore();
@@ -310,13 +311,28 @@
 	}
 
 	public void associateSrc(ClassLoader cl, URL src) {
-		PluginDebug.debug("Associating " + cl + " with " + src);
-		this.classLoaders.put(cl, src);
+	    PluginDebug.debug("Associating " + cl + " with " + src);
+	    this.classLoaders.put(cl, src);
 	}
+	
+    public void associateInstance(Integer i, ClassLoader cl) {
+        PluginDebug.debug("Associating " + cl + " with instance " + i);
+        this.instanceClassLoaders.put(i, cl);
+    }
 
 	public static void setStreamhandler(PluginStreamHandler sh) {
 		streamhandler = sh;
 	}
+	
+	public static Map<String, String> getLoaderInfo() {
+	    Hashtable<String, String> map = new Hashtable<String, String>();
+
+	    for (ClassLoader loader : PluginAppletSecurityContext.classLoaders.keySet()) {
+	        map.put(loader.getClass().getName(), classLoaders.get(loader).toString());
+	    }
+
+	    return map;
+	}
 
 	public void handleMessage(int reference, String src, AccessControlContext callContext, String message) {
 
@@ -327,15 +343,31 @@
 				ClassLoader cl = null;
 				Class c = null;
 				cl = liveconnectLoader;
-				String className = message.substring("FindClass".length() + 1)
-						.replace('/', '.');
+				String[] args = message.split(" ");
+				Integer instance = new Integer(args[1]);
+				String className = args[2].replace('/', '.');
+				PluginDebug.debug("Searching for class " + className + " in " + cl);
 
 				try {
 					c = cl.loadClass(className);
 					store.reference(c);
 					write(reference, "FindClass " + store.getIdentifier(c));
 				} catch (ClassNotFoundException cnfe) {
-					write(reference, "FindClass 0");
+				    
+			        cl = this.instanceClassLoaders.get(instance);
+			        PluginDebug.debug("Not found. Looking in " + cl);
+			        
+                    if (instance != 0 && cl != null) {				    
+				        try {
+				            c = cl.loadClass(className);
+				            store.reference(c);
+				            write(reference, "FindClass " + store.getIdentifier(c));
+				        } catch (ClassNotFoundException cnfe2) {
+				            write(reference, "FindClass 0");
+				        }
+				    } else {
+				        write(reference, "FindClass 0");
+				    }
 				}
 
 			} else if (message.startsWith("GetStaticMethodID")
@@ -410,85 +442,40 @@
 				if (ret instanceof Throwable)
 					throw (Throwable) ret;
 
-				// System.out.println ("FIELD VALUE: " + ret);
-				if (ret == null) {
-					write(reference, "GetStaticField 0");
-				} else if (f.getType() == Boolean.TYPE
-						|| f.getType() == Byte.TYPE
-						|| f.getType() == Character.TYPE
-						|| f.getType() == Short.TYPE
-						|| f.getType() == Integer.TYPE
-						|| f.getType() == Long.TYPE
-						|| f.getType() == Float.TYPE
-						|| f.getType() == Double.TYPE) {
-					write(reference, "GetStaticField " + ret);
-				} else {
-					// Track returned object.
-					store.reference(ret);
-					write(reference, "GetStaticField "
-							+ store.getIdentifier(ret));
-				}
-			} else if (message.startsWith("SetStaticField")) {
+                if (ret == null) {
+                    write(reference, "GetStaticField literalreturn null");
+                } else if (f.getType() == Boolean.TYPE
+                        || f.getType() == Byte.TYPE
+                        || f.getType() == Short.TYPE
+                        || f.getType() == Integer.TYPE
+                        || f.getType() == Long.TYPE) {
+                    write(reference, "GetStaticField literalreturn " + ret);
+                } else if (f.getType() == Float.TYPE
+                		|| f.getType() == Double.TYPE) {
+                	write(reference, "GetStaticField literalreturn " + String.format("%308.308e", ret));
+                } else if (f.getType() == Character.TYPE) {
+                    write(reference, "GetStaticField literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetStaticField " + store.getIdentifier(ret));
+                }
+			} else if (message.startsWith("SetStaticField") ||
+			           message.startsWith("SetField")) {
 				String[] args = message.split(" ");
-				String type = parseCall(args[1], null, String.class);
-				Integer classID = parseCall(args[2], null, Integer.class);
-				Integer fieldID = parseCall(args[3], null, Integer.class);
+				Integer classOrObjectID = parseCall(args[1], null, Integer.class);
+				Integer fieldID = parseCall(args[2], null, Integer.class);
+				Object value = store.getObject(parseCall(args[3], null, Integer.class));
 
-				Object value = null;
-				if (Signature.primitiveNameToType(type) != null) {
-					value = parseArgs(args[4], Signature
-							.primitiveNameToType(type));
-					// System.out.println ("HERE1: " + value);
-				} else {
-					value = parseArgs(args[3], Object.class);
-					// System.out.println ("HERE2: " + value);
-				}
-
-				final Class c = (Class) store.getObject(classID);
+				final Object o = store.getObject(classOrObjectID);
 				final Field f = (Field) store.getObject(fieldID);
 
-				final Object fValue = value;
-				AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
-				checkPermission(src, c, acc);
-
-				Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () {
-					public Object run() {
-						try {
-							f.set(c, fValue);
-						} catch (Throwable t) {
-							return t;
-						}
-						
-						return null;
-					}
-				}, acc);
-
-				if (ret instanceof Throwable)
-					throw (Throwable) ret;
+				final Object fValue = MethodOverloadResolver.getCostAndCastedObject(value, f.getType())[1];
 
-				write(reference, "SetStaticField");
-			} else if (message.startsWith("SetField")) {
-				String[] args = message.split(" ");
-				String type = parseCall(args[1], null, String.class);
-				Integer objectID = parseCall(args[2], null, Integer.class);
-				Integer fieldID = parseCall(args[3], null, Integer.class);
-
-				Object value = null;
-				if (Signature.primitiveNameToType(type) != null) {
-					value = parseArgs(args[4], Signature
-							.primitiveNameToType(type));
-					// System.out.println ("HERE1: " + value);
-				} else {
-					value = parseArgs(args[3], Object.class);
-					// System.out.println ("HERE2: " + value);
-				}
-
-				final Object o = (Object) store.getObject(objectID);
-				final Field f = (Field) store.getObject(fieldID);
-
-				final Object fValue = value;
 				AccessControlContext acc = callContext != null ? callContext : getClosedAccessControlContext();
-				checkPermission(src, o.getClass(), acc);
+				checkPermission(src, 
+				                message.startsWith("SetStaticField") ? (Class) o : o.getClass(), 
+				                acc);
 
 				Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () {
 					public Object run() {
@@ -511,26 +498,45 @@
 				Integer arrayID = parseCall(args[1], null, Integer.class);
 				Integer index = parseCall(args[2], null, Integer.class);
 
-				Object[] o = (Object[]) store.getObject(arrayID);
-				Object ret = null;
-
-				ret = o[index];
+				Object ret = Array.get(store.getObject(arrayID), index);
+				Class retClass = store.getObject(arrayID).getClass().getComponentType(); // prevent auto-boxing influence
+				
+                if (ret == null) {
+                    write(reference, "GetObjectArrayElement literalreturn null");
+                } else if (retClass == Boolean.TYPE
+                        || retClass == Byte.TYPE
+                        || retClass == Short.TYPE
+                        || retClass== Integer.TYPE
+                        || retClass== Long.TYPE) {
+                    write(reference, "GetObjectArrayElement literalreturn " + ret);
+                } else if (retClass == Float.TYPE
+                		|| retClass == Double.TYPE) {
+                	write(reference, "GetObjectArrayElement literalreturn " + String.format("%308.308e", ret));                    
+                } else if (retClass == Character.TYPE) {
+                    write(reference, "GetObjectArrayElement literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetObjectArrayElement " + store.getIdentifier(ret));
+                }				
 
-				// Track returned object.
-				store.reference(ret);
-				// System.out.println ("array element: " + index + " " + ret);
-				write(reference, "GetObjectArrayElement "
-						+ store.getIdentifier(ret));
 			} else if (message.startsWith("SetObjectArrayElement")) {
 				String[] args = message.split(" ");
 				Integer arrayID = parseCall(args[1], null, Integer.class);
 				Integer index = parseCall(args[2], null, Integer.class);
 				Integer objectID = parseCall(args[3], null, Integer.class);
 
-				Object[] o = (Object[]) store.getObject(arrayID);
-				Object toSet = (Object) store.getObject(objectID);
-
-				o[index] = toSet;
+				// Reflecting doesn't handle Integer -> char dynamic casting 
+				// very well in this case. Give it a little push...
+				if (store.getObject(arrayID).getClass().getComponentType().equals(java.lang.Character.class) ||
+				    store.getObject(arrayID).getClass().getComponentType().equals(java.lang.Character.TYPE))
+				{
+				    char c = (char) ((Integer) store.getObject(objectID)).intValue();
+				    System.err.println("Char array set to " + c + "(" + store.getObject(objectID) + ")");
+				    Array.set(store.getObject(arrayID), index, c);				    
+				} else {
+				    Array.set(store.getObject(arrayID), index, store.getObject(objectID));				    
+				}
 
 				write(reference, "SetObjectArrayElement");
 			} else if (message.startsWith("GetArrayLength")) {
@@ -570,23 +576,25 @@
 				if (ret instanceof Throwable)
 					throw (Throwable) ret;
 
-				// System.out.println ("FIELD VALUE: " + ret);
-				if (ret == null) {
-					write(reference, "GetField 0");
-				} else if (f.getType() == Boolean.TYPE
-						|| f.getType() == Byte.TYPE
-						|| f.getType() == Character.TYPE
-						|| f.getType() == Short.TYPE
-						|| f.getType() == Integer.TYPE
-						|| f.getType() == Long.TYPE
-						|| f.getType() == Float.TYPE
-						|| f.getType() == Double.TYPE) {
-					write(reference, "GetField " + ret);
-				} else {
-					// Track returned object.
-					store.reference(ret);
-					write(reference, "GetField " + store.getIdentifier(ret));
-				}
+                if (ret == null) {
+                    write(reference, "GetField literalreturn null");
+                } else if (f.getType() == Boolean.TYPE
+                        || f.getType() == Byte.TYPE
+                        || f.getType() == Short.TYPE
+                        || f.getType() == Integer.TYPE
+                        || f.getType() == Long.TYPE) {
+                    write(reference, "GetField literalreturn " + ret);
+                } else if (f.getType() == Float.TYPE
+                		|| f.getType() == Double.TYPE) {
+                	write(reference, "GetField literalreturn " + String.format("%308.308e", ret));
+                } else if (f.getType() == Character.TYPE) {
+                    write(reference, "GetField literalreturn " + (int) (Character) ret);
+                } else {
+                    // Track returned object.
+                    store.reference(ret);
+                    write(reference, "GetField " + store.getIdentifier(ret));
+                }
+
 			} else if (message.startsWith("GetObjectClass")) {
 				int oid = Integer.parseInt(message.substring("GetObjectClass"
 						.length() + 1));
@@ -648,6 +656,9 @@
 
 				final Object[] fArguments = castedArgs;
 				final Object callableObject = o;
+				// Set the method accessible prior to calling. See:
+				// http://forums.sun.com/thread.jspa?threadID=332001&start=15&tstart=0
+				m.setAccessible(true);
 				Object ret = AccessController.doPrivileged(new PrivilegedAction<Object> () {
 					public Object run() {
 						try {
@@ -665,44 +676,29 @@
 				if (ret == null) {
 					retO = "null";
 				} else {
-					retO = ret.getClass().toString();
+					retO = m.getReturnType().toString();
 				}
 
 				PluginDebug.debug("Calling " + m + " on " + o + " with "
 						+ collapsedArgs + " and that returned: " + ret
 						+ " of type " + retO);
 
-				if (ret == null) {
-					write(reference, "CallMethod literalreturn void");
+				if (m.getReturnType().equals(java.lang.Void.class) || 
+				    m.getReturnType().equals(java.lang.Void.TYPE)) {
+                    write(reference, "CallMethod literalreturn void");
+                } else if (ret == null) {
+					write(reference, "CallMethod literalreturn null");
 				} else if (m.getReturnType() == Boolean.TYPE
 						|| m.getReturnType() == Byte.TYPE
 						|| m.getReturnType() == Short.TYPE
 						|| m.getReturnType() == Integer.TYPE
-						|| m.getReturnType() == Long.TYPE
-						|| m.getReturnType() == Float.TYPE
-						|| m.getReturnType() == Double.TYPE
-						|| m.getReturnType() == Boolean.class
-                        || m.getReturnType() == Byte.class
-                        || m.getReturnType() == Short.class
-                        || m.getReturnType() == Integer.class
-                        || m.getReturnType() == Long.class
-                        || m.getReturnType() == Float.class
-                        || m.getReturnType() == Double.class) {
+						|| m.getReturnType() == Long.TYPE) {
 					write(reference, "CallMethod literalreturn " + ret);
-				} else if (m.getReturnType() == Character.TYPE
-				        || m.getReturnType() == Character.class) {
-				    String s = new String(new char[] {(Character) ret});
-				    byte[] b = null;
-				    b = s.getBytes("UTF-8");
-				    StringBuffer buf = new StringBuffer(b.length * 2);
-				    buf.append(b.length);
-				    for (int i = 0; i < b.length; i++)
-				        buf
-				        .append(" "
-				                + Integer
-				                .toString(((int) b[i]) & 0x0ff, 16));
-					
-					write(reference, "CallMethod literalreturn " + buf);
+                } else if (m.getReturnType() == Float.TYPE
+                		|| m.getReturnType() == Double.TYPE) {
+                	write(reference, "CallMethod literalreturn " + String.format("%308.308e", ret));  
+				} else if (m.getReturnType() == Character.TYPE) {
+					write(reference, "CallMethod literalreturn " +  (int) (Character) ret);
 				} else {
 					// Track returned object.
 					store.reference(ret);
@@ -864,7 +860,8 @@
                 write(reference, "HasMethod " + hasMethod);
             } else if (message.startsWith("HasPackage")) {
                 String[] args = message.split(" ");
-                Integer nameID = parseCall(args[1], null, Integer.class);
+                Integer instance = parseCall(args[1], null, Integer.class);
+                Integer nameID = parseCall(args[2], null, Integer.class);
                 String pkgName = (String) store.getObject(nameID);
 
                 Package pkg = Package.getPackage(pkgName);
@@ -1138,7 +1135,7 @@
 		streamhandler.write("context " + identifier + " reference " + reference
 				+ " " + message);
 	}
-	
+
 	public void prePopulateLCClasses() {
 		
 		int classID;
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Thu Aug 27 13:16:24 2009 -0400
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java	Tue Sep 15 12:47:59 2009 -0400
@@ -316,14 +316,32 @@
  	// Wait for the panel to initialize
     // (happens in a separate thread)
  	Applet a;
-    while ((a = panel.getApplet()) == null && ((NetxPanel) panel).isAlive()) {
-   	 try {
-   		 Thread.sleep(1000);
-   		 PluginDebug.debug("Waiting for applet to initialize... ");
-   	 } catch (InterruptedException ie) {
-   		 ie.printStackTrace();
-   	 }
+ 	
+ 	// Wait for panel to come alive
+ 	int maxWait = 5000; // wait 5 seconds max for panel to come alive
+ 	int wait = 0;
+ 	while ((panel == null) || (!((NetxPanel) panel).isAlive() && wait < maxWait)) {
+         try {
+             Thread.sleep(50);
+             wait += 50;
+         } catch (InterruptedException ie) {
+             ie.printStackTrace();
+         }
     }
+ 	
+    // Wait for the panel to initialize
+    // (happens in a separate thread)
+    while (panel.getApplet() == null &&
+           ((NetxPanel) panel).isAlive()) {
+        try {
+            Thread.sleep(50);
+            PluginDebug.debug("Waiting for applet to initialize...");
+        } catch (InterruptedException ie) {
+            ie.printStackTrace();
+        }
+    }
+ 	
+    a = panel.getApplet();
 
     // Still null?
     if (panel.getApplet() == null) {
@@ -331,7 +349,7 @@
     	return;
     }
 
-    PluginDebug.debug("Applet initialized");
+    PluginDebug.debug("Applet " + a.getClass() + " initialized");
 
     // Applet initialized. Find out it's classloader and add it to the list
     String portComponent = doc.getPort() != -1 ? ":" + doc.getPort() : "";
@@ -346,7 +364,8 @@
     	}
     }
 
-    AppletSecurityContextManager.getSecurityContext(0).associateSrc(a.getClass().getClassLoader(), doc);
+    AppletSecurityContextManager.getSecurityContext(0).associateSrc(((NetxPanel) panel).getAppletClassLoader(), doc);
+    AppletSecurityContextManager.getSecurityContext(0).associateInstance(identifier, ((NetxPanel) panel).getAppletClassLoader());
     
  	try {
  	    write("initialized");
@@ -523,8 +542,7 @@
                  status.put(identifier, PAV_INIT_STATUS.INACTIVE);
 
              throw new RuntimeException("Failed to handle message: " + 
-                     message + " for instance " + identifier + " " +  
-                     Thread.currentThread(), e);
+                     message + " for instance " + identifier, e);
          }
      }
  
@@ -579,23 +597,39 @@
              // object should belong to?
              Object o;
 
+             // Wait for panel to come alive
+             int maxWait = 5000; // wait 5 seconds max for panel to come alive
+             int wait = 0;
+             while ((panel == null) || (!((NetxPanel) panel).isAlive() && wait < maxWait)) {
+                  try {
+                      Thread.sleep(50);
+                      wait += 50;
+                  } catch (InterruptedException ie) {
+                      ie.printStackTrace();
+                  }
+             }
+             
              // Wait for the panel to initialize
              // (happens in a separate thread)
-             while (panel == null || ((o = panel.getApplet()) == null && ((NetxPanel) panel).isAlive())) {
-            	 try {
-            		 Thread.sleep(2000);
-            		 PluginDebug.debug("Waiting for applet to initialize...");
-            	 } catch (InterruptedException ie) {
-            		 ie.printStackTrace();
-            	 }
+             while (panel.getApplet() == null &&
+                    ((NetxPanel) panel).isAlive()) {
+                 try {
+                     Thread.sleep(50);
+                     PluginDebug.debug("Waiting for applet to initialize...");
+                 } catch (InterruptedException ie) {
+                     ie.printStackTrace();
+                 }
              }
 
+             PluginDebug.debug(panel + " -- " + panel.getApplet() + " -- " + ((NetxPanel) panel).isAlive());
+
              // Still null?
              if (panel.getApplet() == null) {
                  this.streamhandler.write("instance " + identifier + " reference " + -1 + " fatalError " + "Initialization failed");
                  return;
              }
 
+             o = panel.getApplet();
              PluginDebug.debug ("Looking for object " + o + " panel is " + panel);
              AppletSecurityContextManager.getSecurityContext(0).store(o);
              PluginDebug.debug ("WRITING 1: " + "context 0 reference " + reference + " GetJavaObject "