Initial checkin of OOPHM plugins into trunk.  Testing of non-XPCOM plugins
is still required, and more platforms need to be built.


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@5868 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/plugins/npapi/JavaObject.cpp b/plugins/npapi/JavaObject.cpp
new file mode 100644
index 0000000..16f7a09
--- /dev/null
+++ b/plugins/npapi/JavaObject.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+#include "Debug.h"
+
+#include "JavaObject.h"
+#include "Plugin.h"
+#include "NPVariantWrapper.h"
+
+using std::string;
+
+static string IdentifierName(NPIdentifier name) {
+  string iname;
+  if (NPN_IdentifierIsString(name)) {
+    iname = NPN_UTF8FromIdentifier(name);
+  } else {
+    char buf[50];
+    snprintf(buf, sizeof(buf), "%d", NPN_IntFromIdentifier(name));
+    iname = buf;
+  }
+  return iname;
+}
+
+JavaObject* JavaObject::create(ScriptableInstance* plugin, int id) {
+  Debug::log(Debug::Spam) << "Creating Java object id=" << id;
+  NPClass* npClass = GetNPClass<JavaObject>();
+  NPObject* obj = NPN_CreateObject(plugin->getNPP(), npClass);
+  Debug::log(Debug::Spam) << " addr=" << obj << Debug::flush;
+  JavaObject* jObj = static_cast<JavaObject*>(obj);
+  jObj->setObjectId(id);
+  return jObj;
+}
+
+bool JavaObject::isInstance(NPObject* obj) {
+  return obj->_class == GetNPClass<JavaObject>();
+}
+
+JavaObject::~JavaObject() {
+  if (plugin) {
+    plugin->destroyJavaWrapper(this);
+  } else {
+    Debug::log(Debug::Spam) << "Destroying JavaObject " << objectId << " after plugin destroyed"
+        << Debug::flush;
+  }
+}
+
+bool JavaObject::enumeration(NPIdentifier** propReturn, uint32_t* count) {
+  Debug::log(Debug::Debugging) << "JavaObject::enumeration(" << objectId << ")"
+      << Debug::flush;
+  int n = 1;
+  NPIdentifier* props = static_cast<NPIdentifier*>(NPN_MemAlloc(sizeof(NPIdentifier) * n));
+  props[0] = idID;
+  *propReturn = props;
+  *count = n;
+  return true;
+}
+
+bool JavaObject::getProperty(NPIdentifier prop, NPVariant *result) {
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring getProperty on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    VOID_TO_NPVARIANT(*result);
+    return true;
+  }
+  Debug::log(Debug::Spam) << "JavaObject::getProperty(" << objectId << ")" << Debug::flush;
+  if (NPN_IdentifierIsString(prop)) {
+    if (prop == plugin->toStringID) {
+      return plugin->JavaObject_getToStringTearOff(result);
+    }
+    if (prop == idID) {
+      INT32_TO_NPVARIANT(objectId, *result);
+      return true;
+    }
+    // all other properties are numeric dispatchIDs
+    return false;
+  }
+  int dispId = NPN_IntFromIdentifier(prop);
+  // JavaObject_getProperty will retain the return value if needed.
+  return plugin->JavaObject_getProperty(objectId, dispId, result);
+}
+
+bool JavaObject::hasMethod(NPIdentifier method) {
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring hasMethod on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    return true;
+  }
+  Debug::log(Debug::Spam) << "JavaObject::hasMethod(" << objectId << ", method="
+      << IdentifierName(method) << ")" << Debug::flush;
+  return false;
+//  return !NPN_IdentifierIsString(method);
+}
+
+bool JavaObject::hasProperty(NPIdentifier prop) {
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring hasProperty on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    return true;
+  }
+  Debug::log(Debug::Spam) << "JavaObject::hasProperty(" << objectId << ", prop="
+      << IdentifierName(prop) << ")" << Debug::flush;
+  return !NPN_IdentifierIsString(prop) || prop == idID || prop == plugin->toStringID;
+}
+
+bool JavaObject::invokeDefault(const NPVariant *args, uint32_t argCount, NPVariant *result) {
+  if (argCount < 2 || !NPVariantProxy::isInt(args[0])
+      || (!NPVariantProxy::isNull(args[1]) && !NPVariantProxy::isObject(args[1]))) {
+    Debug::log(Debug::Error) << "incorrect arguments to invokeDefault" << Debug::flush;
+    return false;
+  }
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring invokeDefault on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    VOID_TO_NPVARIANT(*result);
+    return true;
+  }
+  Debug::log(Debug::Debugging) << "JavaObject::invokeDefault(" << objectId;
+  for (uint32_t i = 0; i < argCount; ++i) {
+    Debug::log(Debug::Debugging) << ", " << NPVariantProxy::toString(args[i]);
+  }
+  Debug::log(Debug::Debugging) << ")" << Debug::flush;
+  int dispId = NPVariantProxy::getAsInt(args[0]);
+  int objId = objectId;
+  if (!NPVariantProxy::isNull(args[1])) {
+    NPObject* thisObj = NPVariantProxy::getAsObject(args[1]);
+    if (isInstance(thisObj)) {
+      JavaObject* thisJavaObj = static_cast<JavaObject*>(thisObj);
+      objId = thisJavaObj->objectId;
+    }
+  }
+  // JavaObject_invoke will retain the return value if needed.
+  return plugin->JavaObject_invoke(objId, dispId, args + 2, argCount - 2, result);
+}
+
+bool JavaObject::invoke(NPIdentifier name, const NPVariant *args,
+    uint32_t argCount, NPVariant *result) {
+  VOID_TO_NPVARIANT(*result);
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring invoke on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    return true;
+  }
+  string methodName(NPN_UTF8FromIdentifier(name));
+  Debug::log(Debug::Spam) << "JavaObject::invoke(" << objectId << ", method="
+      << methodName << ")" << Debug::flush;
+  if (name == plugin->toStringID) {
+    // -1 is magic and means a raw toString().
+    return plugin->JavaObject_invoke(objectId, -1, args, argCount, result);
+  }
+  // toString is the only method we support invoking directly on a Java wrapper
+  return false;
+}
+
+bool JavaObject::setProperty(NPIdentifier prop, const NPVariant *value) {
+  if (!plugin) {
+    Debug::log(Debug::Spam) << "Ignoring setProperty on " << objectId << " after plugin destroyed"
+        << Debug::flush;
+    return true;
+  }
+  Debug::log(Debug::Spam) << "JavaObject::setProperty(" << objectId << ", val="
+      << NPVariantProxy::toString(*value) << ")" << Debug::flush;
+  if (NPN_IdentifierIsString(prop)) {
+    // any non-numeric properties are read-only
+    return false;
+  }
+  int dispId = NPN_IntFromIdentifier(prop); 
+  return plugin->JavaObject_setProperty(objectId, dispId, value);
+}