diff options
Diffstat (limited to 'V8Binding/jni')
-rw-r--r-- | V8Binding/jni/jni_class.cpp | 146 | ||||
-rw-r--r-- | V8Binding/jni/jni_class.h | 53 | ||||
-rw-r--r-- | V8Binding/jni/jni_instance.cpp | 228 | ||||
-rw-r--r-- | V8Binding/jni/jni_instance.h | 89 | ||||
-rw-r--r-- | V8Binding/jni/jni_npobject.cpp | 46 | ||||
-rw-r--r-- | V8Binding/jni/jni_npobject.h | 27 | ||||
-rw-r--r-- | V8Binding/jni/jni_runtime.cpp | 169 | ||||
-rw-r--r-- | V8Binding/jni/jni_runtime.h | 124 | ||||
-rw-r--r-- | V8Binding/jni/jni_utility.cpp | 474 | ||||
-rw-r--r-- | V8Binding/jni/jni_utility.h | 281 |
10 files changed, 1637 insertions, 0 deletions
diff --git a/V8Binding/jni/jni_class.cpp b/V8Binding/jni/jni_class.cpp new file mode 100644 index 0000000..4e3b5f9 --- /dev/null +++ b/V8Binding/jni/jni_class.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "jni_class.h" + +#if ENABLE(MAC_JAVA_BRIDGE) + +#include "JSDOMWindow.h" +#include <runtime/Identifier.h> +#include <runtime/JSLock.h> +#include "jni_utility.h" +#include "jni_runtime.h" + +using namespace JSC::Bindings; + +JavaClass::JavaClass(jobject anInstance) +{ + jobject aClass = callJNIMethod<jobject>(anInstance, "getClass", "()Ljava/lang/Class;"); + + if (!aClass) { + fprintf(stderr, "%s: unable to call getClass on instance %p\n", __PRETTY_FUNCTION__, anInstance); + return; + } + + jstring className = (jstring)callJNIMethod<jobject>(aClass, "getName", "()Ljava/lang/String;"); + const char *classNameC = getCharactersFromJString(className); + _name = strdup(classNameC); + releaseCharactersForJString(className, classNameC); + + int i; + JNIEnv *env = getJNIEnv(); + + // Get the fields + jarray fields = (jarray)callJNIMethod<jobject>(aClass, "getFields", "()[Ljava/lang/reflect/Field;"); + int numFields = env->GetArrayLength(fields); + for (i = 0; i < numFields; i++) { + jobject aJField = env->GetObjectArrayElement((jobjectArray)fields, i); + JavaField *aField = new JavaField(env, aJField); // deleted in the JavaClass destructor + { + JSLock lock(false); + _fields.set(aField->name(), aField); + } + env->DeleteLocalRef(aJField); + } + + // Get the methods + jarray methods = (jarray)callJNIMethod<jobject>(aClass, "getMethods", "()[Ljava/lang/reflect/Method;"); + int numMethods = env->GetArrayLength(methods); + for (i = 0; i < numMethods; i++) { + jobject aJMethod = env->GetObjectArrayElement((jobjectArray)methods, i); + JavaMethod *aMethod = new JavaMethod(env, aJMethod); // deleted in the JavaClass destructor + MethodList* methodList; + { + JSLock lock(false); + + methodList = _methods.get(aMethod->name()); + if (!methodList) { + methodList = new MethodList(); + _methods.set(aMethod->name(), methodList); + } + } + methodList->append(aMethod); + env->DeleteLocalRef(aJMethod); + } +#ifdef ANDROID_FIX + env->DeleteLocalRef(fields); + env->DeleteLocalRef(methods); + env->DeleteLocalRef(aClass); +#endif +} + +JavaClass::~JavaClass() { + free((void *)_name); + + JSLock lock(false); + + deleteAllValues(_fields); + _fields.clear(); + + MethodListMap::const_iterator end = _methods.end(); + for (MethodListMap::const_iterator it = _methods.begin(); it != end; ++it) { + const MethodList* methodList = it->second; + deleteAllValues(*methodList); + delete methodList; + } + _methods.clear(); +} + +MethodList JavaClass::methodsNamed(const Identifier& identifier, Instance*) const +{ + MethodList *methodList = _methods.get(identifier.ustring().rep()); + + if (methodList) + return *methodList; + return MethodList(); +} + +Field *JavaClass::fieldNamed(const Identifier& identifier, Instance*) const +{ + return _fields.get(identifier.ustring().rep()); +} + +bool JavaClass::isNumberClass() const +{ + return ((strcmp(_name, "java.lang.Byte") == 0 || + strcmp(_name, "java.lang.Short") == 0 || + strcmp(_name, "java.lang.Integer") == 0 || + strcmp(_name, "java.lang.Long") == 0 || + strcmp(_name, "java.lang.Float") == 0 || + strcmp(_name, "java.lang.Double") == 0) ); +} + +bool JavaClass::isBooleanClass() const +{ + return strcmp(_name, "java.lang.Boolean") == 0; +} + +bool JavaClass::isStringClass() const +{ + return strcmp(_name, "java.lang.String") == 0; +} + +#endif // ENABLE(MAC_JAVA_BRIDGE) diff --git a/V8Binding/jni/jni_class.h b/V8Binding/jni/jni_class.h new file mode 100644 index 0000000..2865be5 --- /dev/null +++ b/V8Binding/jni/jni_class.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JNI_CLASS_H_ +#define JNI_CLASS_H_ + +#include <jni_runtime.h> +#include <wtf/HashMap.h> + +namespace JSC { + +namespace Bindings { + +typedef Vector<JavaMethod*> MethodList; +class JavaClass +public: + JavaClass (jobject anInstance); + ~JavaClass (); + + MethodList methodsNamed(NPIdentifier name, Instance* instance) const; + +private: + const char *_name; + MethodListMap _methods; +}; + +} // namespace Bindings + +} // namespace JSC + +#endif // JNI_CLASS_H_ diff --git a/V8Binding/jni/jni_instance.cpp b/V8Binding/jni/jni_instance.cpp new file mode 100644 index 0000000..887886e --- /dev/null +++ b/V8Binding/jni/jni_instance.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2003, 2008 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "jni_instance.h" +#include "jni_runtime.h" +#include "jni_utility.h" + +#include <assert.h> + +#ifdef NDEBUG +#define JS_LOG(formatAndArgs...) ((void)0) +#else +#define JS_LOG(formatAndArgs...) { \ + fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \ + fprintf(stderr, formatAndArgs); \ +} +#endif + +using namespace JSC::Bindings; + +JavaInstance::JavaInstance (jobject instance) +{ + _instance = new JObjectWrapper (instance); +} + +JavaInstance::~JavaInstance () +{ +} + +#define NUM_LOCAL_REFS 64 + +bool JavaInstance::invokeMethod(NPIdentifier methodName, NPVariant* args, uint32_t count, NPVariant* resultValue) +{ + int i; + jvalue *jArgs; + Method *method = 0; + size_t numMethods = methodList.size(); + + // Try to find a good match for the overloaded method. The + // fundamental problem is that JavaScript doesn have the + // notion of method overloading and Java does. We could + // get a bit more sophisticated and attempt to does some + // type checking as we as checking the number of parameters. + Method *aMethod; + for (size_t methodIndex = 0; methodIndex < numMethods; methodIndex++) { + aMethod = methodList[methodIndex]; + if (aMethod->numParameters() == count) { + method = aMethod; + break; + } + } + if (method == 0) { + JS_LOG ("unable to find an appropiate method\n"); + return jsUndefined(); + } + + const JavaMethod *jMethod = static_cast<const JavaMethod*>(method); + + if (count > 0) { + jArgs = (jvalue *)malloc (count * sizeof(jvalue)); + } + else + jArgs = 0; + + for (i = 0; i < count; i++) { + JavaParameter* aParameter = jMethod->parameterAt(i); + jArgs[i] = convertNPVariantToJValue(args[i], aParameter->getJNIType(), aParameter->type()); + } + + jvalue result; + + // The following code can be conditionally removed once we have a Tiger update that + // contains the new Java plugin. It is needed for builds prior to Tiger. + { + jobject obj = _instance->_instance; + switch (jMethod->JNIReturnType()){ + case void_type: + callJNIMethodIDA<void>(obj, jMethod->methodID(obj), jArgs); + break; + case object_type: + result.l = callJNIMethodIDA<jobject>(obj, jMethod->methodID(obj), jArgs); + break; + case boolean_type: + result.z = callJNIMethodIDA<jboolean>(obj, jMethod->methodID(obj), jArgs); + break; + case byte_type: + result.b = callJNIMethodIDA<jbyte>(obj, jMethod->methodID(obj), jArgs); + break; + case char_type: + result.c = callJNIMethodIDA<jchar>(obj, jMethod->methodID(obj), jArgs); + break; + case short_type: + result.s = callJNIMethodIDA<jshort>(obj, jMethod->methodID(obj), jArgs); + break; + case int_type: + result.i = callJNIMethodIDA<jint>(obj, jMethod->methodID(obj), jArgs); + break; + + case long_type: + result.j = callJNIMethodIDA<jlong>(obj, jMethod->methodID(obj), jArgs); + break; + case float_type: + result.f = callJNIMethodIDA<jfloat>(obj, jMethod->methodID(obj), jArgs); + break; + case double_type: + result.d = callJNIMethodIDA<jdouble>(obj, jMethod->methodID(obj), jArgs); + break; + case invalid_type: + default: + break; + } + } + + switch (jMethod->JNIReturnType()){ + case void_type: { + VOID_TO_NPVARIANT(*resultValue); + } + break; + + case object_type: { + if (result.l != 0) { + OBJECT_TO_NPVARIANT(JavaObjectToNPObject(JavaInstance::create(result.l)), *resultValue); + } + else { + VOID_TO_NPVARIANT(*resultValue); + } + } + break; + + case boolean_type: { + BOOLEAN_TO_NPVARIANT(result.z, *resultValue); + } + break; + + case byte_type: { + INT32_TO_NPVARIANT(result.b, *resultValue); + } + break; + + case char_type: { + INT32_TO_NPVARIANT(result.c, *resultValue); + } + break; + + case short_type: { + INT32_TO_NPVARIANT(result.s, *resultValue); + } + break; + + case int_type: { + INT32_TO_NPVARIANT(result.i, *resultValue); + } + break; + + // TODO(fqian): check if cast to double is needed. + case long_type: { + DOUBLE_TO_NPVARIANT(result.j, *resultValue); + } + break; + + case float_type: { + DOUBLE_TO_NPVARIANT(result.f, *resultValue); + } + break; + + case double_type: { + DOUBLE_TO_NPVARIANT(result.d, *resultValue); + } + break; + + case invalid_type: + default: { + VOID_TO_NPVARIANT(*resultValue); + } + break; + } + + free (jArgs); + + return resultValue; +} + +JObjectWrapper::JObjectWrapper(jobject instance) +: _refCount(0) +{ + assert (instance != 0); + + // Cache the JNIEnv used to get the global ref for this java instanace. + // It'll be used to delete the reference. + _env = getJNIEnv(); + + _instance = _env->NewGlobalRef (instance); + + JS_LOG ("new global ref %p for %p\n", _instance, instance); + + if (_instance == NULL) { + fprintf (stderr, "%s: could not get GlobalRef for %p\n", __PRETTY_FUNCTION__, instance); + } +} + +JObjectWrapper::~JObjectWrapper() { + JS_LOG ("deleting global ref %p\n", _instance); + _env->DeleteGlobalRef (_instance); +} diff --git a/V8Binding/jni/jni_instance.h b/V8Binding/jni/jni_instance.h new file mode 100644 index 0000000..5fa4141 --- /dev/null +++ b/V8Binding/jni/jni_instance.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _JNI_INSTANCE_H_ +#define _JNI_INSTANCE_H_ + +#include <JavaVM/jni.h> + +namespace android { +class WeakJavaInstance; +} + +namespace JSC { + +namespace Bindings { + +class JObjectWrapper +{ +friend class RefPtr<JObjectWrapper>; +friend class JavaArray; +friend class JavaInstance; +friend class JavaMethod; +friend class android::WeakJavaInstance; + +protected: + JObjectWrapper(jobject instance); + ~JObjectWrapper(); + + void ref() { _refCount++; } + void deref() + { + if (--_refCount == 0) + delete this; + } + + jobject _instance; + +private: + JNIEnv *_env; + unsigned int _refCount; +}; + +class JavaInstance +{ +public: + static PassRefPtr<JavaInstance> create(jobject instance) + { + return adoptRef(new JavaInstance(instance)); + } + + ~JavaInstance(); + + NPVariant invokeMethod(NPIdentifier methodName, NPVariant* args, uint32_t argsCount); + + jobject javaInstance() const { return _instance->_instance; } + +private: + JavaInstance(jobject instance); + + RefPtr<JObjectWrapper> _instance; +}; + +} // namespace Bindings + +} // namespace JSC + +#endif // _JNI_INSTANCE_H_ diff --git a/V8Binding/jni/jni_npobject.cpp b/V8Binding/jni/jni_npobject.cpp new file mode 100644 index 0000000..daa26a8 --- /dev/null +++ b/V8Binding/jni/jni_npobject.cpp @@ -0,0 +1,46 @@ + +#include "jni_npobject.h" + +namespace V8 { namespace Binding { + +static NPClass JavaNPClass = { + NP_CLASS_STRUCT_VERSION, + 0, // allocate, + 0, // free, + 0, // invalidate + JavaNPObject_HasMethod, + JavaNPObject_Invoke, + 0, // invokeDefault, + JavaNPObject_HasProperty, + JavaNPobject_GetProperty, + JavaNPObject_SetProperty, + 0, // removeProperty + 0, // enumerate + 0 // construct +}; + +NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance> instance) { + JavaNPObject* object = new JavaNPObject(instance); + return static_cast<NPObject*>(object); +} + +bool JavaNPObject_HasMethod(NPObject* obj, NPIdentifier name) { + // FIXME: for now, always pretend the object has the named method. + return true; +} + +bool JavaNPObject_Invoke(NPobject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) { + +} + +bool JavaNPObject_HasProperty(NPObject* obj, NPIdentifier name) { +} + +bool JavaNPObject_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* ressult) { +} + +bool JavaNPObject_SetProperty(NPObject* obj, NPIdentifier name, const NPVariant* value) { + +} + +} } // namespace V8::Binding diff --git a/V8Binding/jni/jni_npobject.h b/V8Binding/jni/jni_npobject.h new file mode 100644 index 0000000..99fe368 --- /dev/null +++ b/V8Binding/jni/jni_npobject.h @@ -0,0 +1,27 @@ +// A wrapper of a JNI value as an NPObject + + +#ifndef JNI_NPOBJECT_H_ +#define JNI_NPOBJECT_H_ + +#include "npapi.h" +#include <JavaVM/jni.h> + +namespace V8 { namespace V8Binding { + +struct JavaNPObject { + NPObject _object; + RefPtr<JavaInstance> _instance; +}; + +NPObject* JavaInstanceToNPObject(PassRefPtr<JavaInstance> instance); + +bool JavaNPObject_HasMethod(NPObject* obj, NPIdentifier name); +bool JavaNPObject_Invoke(NPobject* obj, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result); +bool JavaNPObject_HasProperty(NPObject* obj, NPIdentifier name); +bool JavaNPObject_GetProperty(NPObject* obj, NPIdentifier name, NPVariant* ressult); +bool JavaNPObject_SetProperty(NPObject* obj, NPIdentifier name, const NPVariant* value); + +} } + +#endif JNI_NPOBJECT_H_ diff --git a/V8Binding/jni/jni_runtime.cpp b/V8Binding/jni/jni_runtime.cpp new file mode 100644 index 0000000..1ff640a --- /dev/null +++ b/V8Binding/jni/jni_runtime.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "jni_runtime.h" +#include "jni_utility.h" + +#ifdef NDEBUG +#define JS_LOG(formatAndArgs...) ((void)0) +#else +#define JS_LOG(formatAndArgs...) { \ + fprintf (stderr, "%s:%d -- %s: ", __FILE__, __LINE__, __FUNCTION__); \ + fprintf(stderr, formatAndArgs); \ +} +#endif + +using namespace JSC::Bindings; + +JavaParameter::JavaParameter (JNIEnv *env, jstring type) +{ + _type = JavaString (env, type); + _JNIType = JNITypeFromClassName (_type.UTF8String()); +} + + +JavaMethod::JavaMethod (JNIEnv *env, jobject aMethod) +{ + // Get return type + jobject returnType = callJNIMethod<jobject>(aMethod, "getReturnType", "()Ljava/lang/Class;"); + jstring returnTypeName = (jstring)callJNIMethod<jobject>(returnType, "getName", "()Ljava/lang/String;"); + _returnType =JavaString (env, returnTypeName); + _JNIReturnType = JNITypeFromClassName (_returnType.UTF8String()); + env->DeleteLocalRef (returnType); + env->DeleteLocalRef (returnTypeName); + + // Get method name + jstring methodName = (jstring)callJNIMethod<jobject>(aMethod, "getName", "()Ljava/lang/String;"); + _name = JavaString (env, methodName); + env->DeleteLocalRef (methodName); + + // Get parameters + jarray jparameters = (jarray)callJNIMethod<jobject>(aMethod, "getParameterTypes", "()[Ljava/lang/Class;"); + _numParameters = env->GetArrayLength (jparameters); + _parameters = new JavaParameter[_numParameters]; + + int i; + for (i = 0; i < _numParameters; i++) { + jobject aParameter = env->GetObjectArrayElement ((jobjectArray)jparameters, i); + jstring parameterName = (jstring)callJNIMethod<jobject>(aParameter, "getName", "()Ljava/lang/String;"); + _parameters[i] = JavaParameter(env, parameterName); + env->DeleteLocalRef (aParameter); + env->DeleteLocalRef (parameterName); + } + env->DeleteLocalRef (jparameters); + + // Created lazily. + _signature = 0; + _methodID = 0; + + jclass modifierClass = env->FindClass("java/lang/reflect/Modifier"); + int modifiers = callJNIMethod<jint>(aMethod, "getModifiers", "()I"); + _isStatic = (bool)callJNIStaticMethod<jboolean>(modifierClass, "isStatic", "(I)Z", modifiers); +#ifdef ANDROID_FIX + env->DeleteLocalRef(modifierClass); +#endif +} + +JavaMethod::~JavaMethod() +{ + if (_signature) + free(_signature); + delete [] _parameters; +}; + +// JNI method signatures use '/' between components of a class name, but +// we get '.' between components from the reflection API. +static void appendClassName(UString& aString, const char* className) +{ + ASSERT(JSLock::lockCount() > 0); + + char *result, *cp = strdup(className); + + result = cp; + while (*cp) { + if (*cp == '.') + *cp = '/'; + cp++; + } + + aString.append(result); + + free (result); +} + +const char *JavaMethod::signature() const +{ + if (!_signature) { + JSLock lock(false); + + UString signatureBuilder("("); + for (int i = 0; i < _numParameters; i++) { + JavaParameter* aParameter = parameterAt(i); + JNIType _JNIType = aParameter->getJNIType(); + if (_JNIType == array_type) + appendClassName(signatureBuilder, aParameter->type()); + else { + signatureBuilder.append(signatureFromPrimitiveType(_JNIType)); + if (_JNIType == object_type) { + appendClassName(signatureBuilder, aParameter->type()); + signatureBuilder.append(";"); + } + } + } + signatureBuilder.append(")"); + + const char *returnType = _returnType.UTF8String(); + if (_JNIReturnType == array_type) { + appendClassName(signatureBuilder, returnType); + } else { + signatureBuilder.append(signatureFromPrimitiveType(_JNIReturnType)); + if (_JNIReturnType == object_type) { + appendClassName(signatureBuilder, returnType); + signatureBuilder.append(";"); + } + } + + _signature = strdup(signatureBuilder.ascii()); + } + + return _signature; +} + +JNIType JavaMethod::JNIReturnType() const +{ + return _JNIReturnType; +} + +jmethodID JavaMethod::methodID (jobject obj) const +{ + if (_methodID == 0) { + _methodID = getMethodID (obj, _name.UTF8String(), signature()); + } + return _methodID; +} + + diff --git a/V8Binding/jni/jni_runtime.h b/V8Binding/jni/jni_runtime.h new file mode 100644 index 0000000..932f26b --- /dev/null +++ b/V8Binding/jni/jni_runtime.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _JNI_RUNTIME_H_ +#define _JNI_RUNTIME_H_ + +#include "jni_utility.h" +#include "jni_instance.h" + +#include "CString.h" + +namespace JSC +{ + +namespace Bindings +{ + +class JavaString +{ +public: + JavaString() { } + + void _commonInit (JNIEnv *e, jstring s) + { + int size = e->GetStringLength(s); + const char* cs = getCharactersFromJStringInEnv(e, s); + { + _utf8String = WebCore::CString(cs, size); + } + releaseCharactersForJStringInEnv (e, s, cs); + } + + JavaString (JNIEnv *e, jstring s) { + _commonInit (e, s); + } + + JavaString (jstring s) { + _commonInit (getJNIEnv(), s); + } + + ~JavaString() { } + + int length() const { return _utf8String->length(); } + + const char* UTF8String() const { + return _utf8String.c_str(); + } + +private: + WebCore::CString _utf8String; +}; + +class JavaParameter +{ +public: + JavaParameter () : _JNIType(invalid_type) {}; + JavaParameter (JNIEnv *env, jstring type); + virtual ~JavaParameter() { } + + const char* type() const { return _type.UTF8String(); } + JNIType getJNIType() const { return _JNIType; } + +private: + JavaString _type; + JNIType _JNIType; +}; + + +class JavaMethod +{ +public: + JavaMethod(JNIEnv* env, jobject aMethod); + ~JavaMethod(); + + const char* name() const { return _name.UTF8String(); } + const char* returnType() const { return _returnType.UTF8String(); }; + JavaParameter* parameterAt(int i) const { return &_parameters[i]; }; + int numParameters() const { return _numParameters; }; + + const char *signature() const; + JNIType JNIReturnType() const; + + jmethodID methodID (jobject obj) const; + + bool isStatic() const { return _isStatic; } + +private: + JavaParameter* _parameters; + int _numParameters; + JavaString _name; + mutable char* _signature; + JavaString _returnType; + JNIType _JNIReturnType; + mutable jmethodID _methodID; + bool _isStatic; +}; + +} // namespace Bindings + +} // namespace JSC + +#endif // _JNI_RUNTIME_H_ diff --git a/V8Binding/jni/jni_utility.cpp b/V8Binding/jni/jni_utility.cpp new file mode 100644 index 0000000..d86dd7b --- /dev/null +++ b/V8Binding/jni/jni_utility.cpp @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "jni_utility.h" +#include "jni_runtime.h" + +#include <dlfcn.h> + +namespace JSC { + +namespace Bindings { + +static jint KJS_GetCreatedJavaVMs(JavaVM** vmBuf, jsize bufLen, jsize* nVMs) +{ + static void* javaVMFramework = 0; + if (!javaVMFramework) + javaVMFramework = dlopen("/System/Library/Frameworks/JavaVM.framework/JavaVM", RTLD_LAZY); + if (!javaVMFramework) + return JNI_ERR; + + static jint(*functionPointer)(JavaVM**, jsize, jsize *) = 0; + if (!functionPointer) + functionPointer = (jint(*)(JavaVM**, jsize, jsize *))dlsym(javaVMFramework, "JNI_GetCreatedJavaVMs"); + if (!functionPointer) + return JNI_ERR; + return functionPointer(vmBuf, bufLen, nVMs); +} + +static JavaVM *jvm = 0; + +// Provide the ability for an outside component to specify the JavaVM to use +// If the jvm value is set, the getJavaVM function below will just return. +// In getJNIEnv(), if AttachCurrentThread is called to a VM that is already +// attached, the result is a no-op. +void setJavaVM(JavaVM *javaVM) +{ + jvm = javaVM; +} + +JavaVM *getJavaVM() +{ + if (jvm) + return jvm; + + JavaVM *jvmArray[1]; + jsize bufLen = 1; + jsize nJVMs = 0; + jint jniError = 0; + + // Assumes JVM is already running ..., one per process + jniError = KJS_GetCreatedJavaVMs(jvmArray, bufLen, &nJVMs); + if ( jniError == JNI_OK && nJVMs > 0 ) { + jvm = jvmArray[0]; + } + else + fprintf(stderr, "%s: JNI_GetCreatedJavaVMs failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError); + + return jvm; +} + +JNIEnv* getJNIEnv() +{ + union { + JNIEnv* env; + void* dummy; + } u; + jint jniError = 0; + + jniError = (getJavaVM())->AttachCurrentThread(&u.dummy, NULL); + if (jniError == JNI_OK) + return u.env; + else + fprintf(stderr, "%s: AttachCurrentThread failed, returned %ld\n", __PRETTY_FUNCTION__, (long)jniError); + return NULL; +} + +jmethodID getMethodID (jobject obj, const char *name, const char *sig) +{ + JNIEnv *env = getJNIEnv(); + jmethodID mid = 0; + + if ( env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + mid = env->GetMethodID(cls, name, sig); + if (!mid) { + env->ExceptionClear(); + mid = env->GetStaticMethodID(cls, name, sig); + if (!mid) { + env->ExceptionClear(); + } + } + } + env->DeleteLocalRef(cls); + } + return mid; +} + +const char *getCharactersFromJString (jstring aJString) +{ + return getCharactersFromJStringInEnv (getJNIEnv(), aJString); +} + +void releaseCharactersForJString (jstring aJString, const char *s) +{ + releaseCharactersForJStringInEnv (getJNIEnv(), aJString, s); +} + +const char *getCharactersFromJStringInEnv (JNIEnv *env, jstring aJString) +{ + jboolean isCopy; + const char *s = env->GetStringUTFChars((jstring)aJString, &isCopy); + if (!s) { + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + return s; +} + +void releaseCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const char *s) +{ + env->ReleaseStringUTFChars (aJString, s); +} + +const jchar *getUCharactersFromJStringInEnv (JNIEnv *env, jstring aJString) +{ + jboolean isCopy; + const jchar *s = env->GetStringChars((jstring)aJString, &isCopy); + if (!s) { + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + return s; +} + +void releaseUCharactersForJStringInEnv (JNIEnv *env, jstring aJString, const jchar *s) +{ + env->ReleaseStringChars (aJString, s); +} + +JNIType JNITypeFromClassName(const char *name) +{ + JNIType type; + + if (strcmp("byte",name) == 0) + type = byte_type; + else if (strcmp("short",name) == 0) + type = short_type; + else if (strcmp("int",name) == 0) + type = int_type; + else if (strcmp("long",name) == 0) + type = long_type; + else if (strcmp("float",name) == 0) + type = float_type; + else if (strcmp("double",name) == 0) + type = double_type; + else if (strcmp("char",name) == 0) + type = char_type; + else if (strcmp("boolean",name) == 0) + type = boolean_type; + else if (strcmp("void",name) == 0) + type = void_type; + else if ('[' == name[0]) + type = array_type; + else + type = object_type; + + return type; +} + +const char *signatureFromPrimitiveType(JNIType type) +{ + switch (type){ + case void_type: + return "V"; + + case array_type: + return "["; + + case object_type: + return "L"; + + case boolean_type: + return "Z"; + + case byte_type: + return "B"; + + case char_type: + return "C"; + + case short_type: + return "S"; + + case int_type: + return "I"; + + case long_type: + return "J"; + + case float_type: + return "F"; + + case double_type: + return "D"; + + case invalid_type: + default: + break; + } + return ""; +} + +JNIType JNITypeFromPrimitiveType(char type) +{ + switch (type){ + case 'V': + return void_type; + + case 'L': + return object_type; + + case '[': + return array_type; + + case 'Z': + return boolean_type; + + case 'B': + return byte_type; + + case 'C': + return char_type; + + case 'S': + return short_type; + + case 'I': + return int_type; + + case 'J': + return long_type; + + case 'F': + return float_type; + + case 'D': + return double_type; + + default: + break; + } + return invalid_type; +} + +jvalue getJNIField( jobject obj, JNIType type, const char *name, const char *signature) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + jvalue result; + + bzero (&result, sizeof(jvalue)); + if ( obj != NULL && jvm != NULL && env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + jfieldID field = env->GetFieldID(cls, name, signature); + if ( field != NULL ) { + switch (type) { + case array_type: + case object_type: + result.l = env->functions->GetObjectField(env, obj, field); + break; + case boolean_type: + result.z = env->functions->GetBooleanField(env, obj, field); + break; + case byte_type: + result.b = env->functions->GetByteField(env, obj, field); + break; + case char_type: + result.c = env->functions->GetCharField(env, obj, field); + break; + case short_type: + result.s = env->functions->GetShortField(env, obj, field); + break; + case int_type: + result.i = env->functions->GetIntField(env, obj, field); + break; + case long_type: + result.j = env->functions->GetLongField(env, obj, field); + break; + case float_type: + result.f = env->functions->GetFloatField(env, obj, field); + break; + case double_type: + result.d = env->functions->GetDoubleField(env, obj, field); + break; + default: + fprintf(stderr, "%s: invalid field type (%d)\n", __PRETTY_FUNCTION__, (int)type); + } + } + else + { + fprintf(stderr, "%s: Could not find field: %s\n", __PRETTY_FUNCTION__, name); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + + env->DeleteLocalRef(cls); + } + else { + fprintf(stderr, "%s: Could not find class for object\n", __PRETTY_FUNCTION__); + } + } + + return result; +} + + +jvalue convertNPVariantToJValue(NPVariant* value, JNIType _JNIType, const char* javaClassName) +{ + jvalue result; + NPVariantType type = value->type; + + switch (_JNIType){ + case array_type: + case object_type: { + result.l = (jobject)0; + + // First see if we have a Java instance. + if (type == NPVariantType_Object) { + NPObject* objectImp = NPVARIANT_TO_OBJECT(*value); + if (objectImp->_class == &JavaNPClass) { + JavaNPObject* imp = static_cast<JavaNPObject*>(objectImp); + JavaInstance *instance = imp->_instance; + if (instance) + result.l = instance->javaInstance(); + } + } + + // Now convert value to a string if the target type is a java.lang.string, and we're not + // converting from a Null. + if (result.l == 0 && strcmp(javaClassName, "java.lang.String") == 0) { +#ifdef CONVERT_NULL_TO_EMPTY_STRING + if (type == NPVariantType_Null) { + JNIEnv *env = getJNIEnv(); + jchar buf[2]; + jobject javaString = env->functions->NewString (env, buf, 0); + result.l = javaString; + } + else +#else + if (type == NPVariantType_String) { +#endif + NPString src = NPVARIANT_TO_STRING(*variant); + JNIEnv *env = getJNIEnv(); + jobject javaString = env->functions->NewStringUTF(env, src.UTF8Characters, src.UTF8Length); + result.l = javaString; + } + } else if (result.l == 0) + bzero (&result, sizeof(jvalue)); // Handle it the same as a void case + } + break; + + case boolean_type: { + if (type == NPVariantType_Boolean) + result.z = NPVARIANT_TO_BOOLEAN(*value); + else + bzero(&result, sizeof(jvalue)); // as void case + } + break; + + case byte_type: { + if (type == NPVariantType_Int32) + result.b = (byte)NPVARIANT_TO_INT32(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case char_type: { + if (type == NPVariantType_Int32) + result.c = (char)NPVARIANT_TO_INT32(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case short_type: { + if (type == NPVariantType_Int32) + result.s = (jshort)NPVARIANT_TO_INT32(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case int_type: { + if (type == NPVariantType_Int32) + result.i = (jint)NPVARIANT_TO_INT32(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case long_type: { + if (type == NPVariantType_Int32) + result.j = (jlong)NPVARIANT_TO_INT32(*value); + else if (type == NPVariantType_Double) + result.j = (jlong)NPVARIANT_TO_DOUBLE(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case float_type: { + if (type == NPVariantType_Int32) + result.j = (jfloat)NPVARIANT_TO_INT32(*value); + else if (type == NPVariantType_Double) + result.j = (jfloat)NPVARIANT_TO_DOUBLE(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + case double_type: { + if (type == NPVariantType_Int32) + result.j = (jdouble)NPVARIANT_TO_INT32(*value); + else if (type == NPVariantType_Double) + result.j = (jdouble)NPVARIANT_TO_DOUBLE(*value); + else + bzero(&result, sizeof(jvalue)); + } + break; + + break; + + case invalid_type: + default: + case void_type: { + bzero (&result, sizeof(jvalue)); + } + break; + } + return result; +} + +} // end of namespace Bindings + +} // end of namespace JSC diff --git a/V8Binding/jni/jni_utility.h b/V8Binding/jni/jni_utility.h new file mode 100644 index 0000000..28b0763 --- /dev/null +++ b/V8Binding/jni/jni_utility.h @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2003 Apple Computer, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _JNI_UTILITY_H_ +#define _JNI_UTILITY_H_ + +#include <JavaVM/jni.h> + +// The order of these items can not be modified as they are tightly +// bound with the JVM on Mac OSX. If new types need to be added, they +// should be added to the end. It is used in jni_obc.mm when calling +// through to the JVM. Newly added items need to be made compatible +// in that file. +typedef enum { + invalid_type = 0, + void_type, + object_type, + boolean_type, + byte_type, + char_type, + short_type, + int_type, + long_type, + float_type, + double_type, + array_type +} JNIType; + +namespace JSC { + +namespace Bindings { + +class JavaParameter; + +const char *getCharactersFromJString(jstring aJString); +void releaseCharactersForJString(jstring aJString, const char *s); + +const char *getCharactersFromJStringInEnv(JNIEnv *env, jstring aJString); +void releaseCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const char *s); +const jchar *getUCharactersFromJStringInEnv(JNIEnv *env, jstring aJString); +void releaseUCharactersForJStringInEnv(JNIEnv *env, jstring aJString, const jchar *s); + +JNIType JNITypeFromClassName(const char *name); +JNIType JNITypeFromPrimitiveType(char type); +const char *signatureFromPrimitiveType(JNIType type); + +jvalue convertNPVariantToJValue(NPVariant*, JNIType, const char* javaClassName); + +jvalue getJNIField(jobject obj, JNIType type, const char *name, const char *signature); + +jmethodID getMethodID(jobject obj, const char *name, const char *sig); +JNIEnv* getJNIEnv(); +JavaVM* getJavaVM(); +void setJavaVM(JavaVM*); + + +template <typename T> struct JNICaller; + +template<> struct JNICaller<void> { + static void callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallVoidMethodA(obj, mid, args); + } + static void callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallVoidMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jobject> { + static jobject callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallObjectMethodA(obj, mid, args); + } + static jobject callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallObjectMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jboolean> { + static jboolean callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallBooleanMethodA(obj, mid, args); + } + static jboolean callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallBooleanMethodV(obj, mid, args); + } + static jboolean callStaticV(jclass cls, jmethodID mid, va_list args) + { + return getJNIEnv()->CallStaticBooleanMethod(cls, mid, args); + } + +}; + +template<> struct JNICaller<jbyte> { + static jbyte callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallByteMethodA(obj, mid, args); + } + static jbyte callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallByteMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jchar> { + static jchar callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallCharMethodA(obj, mid, args); + } + static jchar callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallCharMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jshort> { + static jshort callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallShortMethodA(obj, mid, args); + } + static jshort callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallShortMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jint> { + static jint callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallIntMethodA(obj, mid, args); + } + static jint callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallIntMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jlong> { + static jlong callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallLongMethodA(obj, mid, args); + } + static jlong callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallLongMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jfloat> { + static jfloat callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallFloatMethodA(obj, mid, args); + } + static jfloat callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallFloatMethodV(obj, mid, args); + } +}; + +template<> struct JNICaller<jdouble> { + static jdouble callA(jobject obj, jmethodID mid, jvalue* args) + { + return getJNIEnv()->CallDoubleMethodA(obj, mid, args); + } + static jdouble callV(jobject obj, jmethodID mid, va_list args) + { + return getJNIEnv()->CallDoubleMethodV(obj, mid, args); + } +}; + +template<typename T> T callJNIMethodIDA(jobject obj, jmethodID mid, jvalue *args) +{ + return JNICaller<T>::callA(obj, mid, args); +} + +template<typename T> +static T callJNIMethodV(jobject obj, const char *name, const char *sig, va_list args) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + + if ( obj != NULL && jvm != NULL && env != NULL) { + jclass cls = env->GetObjectClass(obj); + if ( cls != NULL ) { + jmethodID mid = env->GetMethodID(cls, name, sig); + if ( mid != NULL ) + { +#ifdef ANDROID_FIX // Avoids references to cls without popping the local frame. + env->DeleteLocalRef(cls); +#endif + return JNICaller<T>::callV(obj, mid, args); + } + else + { + fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, name, obj); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + + env->DeleteLocalRef(cls); + } + else { + fprintf(stderr, "%s: Could not find class for %p\n", __PRETTY_FUNCTION__, obj); + } + } + + return 0; +} + +template<typename T> +T callJNIMethod(jobject obj, const char* methodName, const char* methodSignature, ...) +{ + va_list args; + va_start(args, methodSignature); + + T result= callJNIMethodV<T>(obj, methodName, methodSignature, args); + + va_end(args); + + return result; +} + +template<typename T> +T callJNIStaticMethod(jclass cls, const char* methodName, const char* methodSignature, ...) +{ + JavaVM *jvm = getJavaVM(); + JNIEnv *env = getJNIEnv(); + va_list args; + + va_start(args, methodSignature); + + T result = 0; + + if (cls != NULL && jvm != NULL && env != NULL) { + jmethodID mid = env->GetStaticMethodID(cls, methodName, methodSignature); + if (mid != NULL) + result = JNICaller<T>::callStaticV(cls, mid, args); + else { + fprintf(stderr, "%s: Could not find method: %s for %p\n", __PRETTY_FUNCTION__, methodName, cls); + env->ExceptionDescribe(); + env->ExceptionClear(); + fprintf (stderr, "\n"); + } + } + + va_end(args); + + return result; +} + +} // namespace Bindings + +} // namespace JSC + +#endif // _JNI_UTILITY_H_ |