Mercurial > hg > release > icedtea7-2.6
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 "