#include "java.h" #include #ifdef WIN32 #else #include #endif #include "javaObject.h" #include "javaScope.h" #include "methodCallBaton.h" #include "node_NodeDynamicProxyClass.h" #include #include long v8ThreadId; /*static*/ v8::Persistent<:functiontemplate> Java::s_ct; /*static*/ std::string Java::s_nativeBindingLocation; void my_sleep(int dur) { #ifdef WIN32 Sleep(dur); #else usleep(dur); #endif } long my_getThreadId() { #ifdef WIN32 return (long)GetCurrentThreadId(); #else return (long)pthread_self(); #endif } /*static*/ void Java::Init(v8::Handle<:object> target) { v8::HandleScope scope; v8ThreadId = my_getThreadId(); v8::Local<:functiontemplate> t = v8::FunctionTemplate::New(New); s_ct = v8::Persistent<:functiontemplate>::New(t); s_ct->InstanceTemplate()->SetInternalFieldCount(1); s_ct->SetClassName(v8::String::NewSymbol("Java")); NODE_SET_PROTOTYPE_METHOD(s_ct, "getClassLoader", getClassLoader); NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstance", newInstance); NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstanceSync", newInstanceSync); NODE_SET_PROTOTYPE_METHOD(s_ct, "newProxy", newProxy); NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethod", callStaticMethod); NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethodSync", callStaticMethodSync); NODE_SET_PROTOTYPE_METHOD(s_ct, "findClassSync", findClassSync); NODE_SET_PROTOTYPE_METHOD(s_ct, "newArray", newArray); NODE_SET_PROTOTYPE_METHOD(s_ct, "newByte", newByte); NODE_SET_PROTOTYPE_METHOD(s_ct, "newShort", newShort); NODE_SET_PROTOTYPE_METHOD(s_ct, "newLong", newLong); NODE_SET_PROTOTYPE_METHOD(s_ct, "newChar", newChar); NODE_SET_PROTOTYPE_METHOD(s_ct, "newFloat", newFloat); NODE_SET_PROTOTYPE_METHOD(s_ct, "newDouble", newDouble); NODE_SET_PROTOTYPE_METHOD(s_ct, "getStaticFieldValue", getStaticFieldValue); NODE_SET_PROTOTYPE_METHOD(s_ct, "setStaticFieldValue", setStaticFieldValue); NODE_SET_PROTOTYPE_METHOD(s_ct, "instanceOf", instanceOf); target->Set(v8::String::NewSymbol("Java"), s_ct->GetFunction()); } /*static*/ v8::Handle<:value> Java::New(const v8::Arguments& args) { v8::HandleScope scope; Java *self = new Java(); self->Wrap(args.This()); self->handle_->Set(v8::String::New("classpath"), v8::Array::New()); self->handle_->Set(v8::String::New("options"), v8::Array::New()); self->handle_->Set(v8::String::New("nativeBindingLocation"), v8::String::New("Not Set")); return args.This(); } Java::Java() { this->m_jvm = NULL; this->m_env = NULL; } Java::~Java() { this->destroyJVM(&this->m_jvm, &this->m_env); } v8::Handle<:value> Java::ensureJvm() { if(!m_jvm) { return createJVM(&this->m_jvm, &this->m_env); } return v8::Undefined(); } v8::Handle<:value> Java::createJVM(JavaVM** jvm, JNIEnv** env) { JavaVM* jvmTemp; JavaVMInitArgs args; // setup classpath std::ostringstream classPath; classPath classPathValue = handle_->Get(v8::String::New("classpath")); if(!classPathValue->IsArray()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Classpath must be an array"))); } v8::Local<:array> classPathArrayTemp = v8::Array::Cast(*classPathValue); m_classPathArray = v8::Persistent<:array>::New(classPathArrayTemp); for(uint32_t i=0; iLength(); i++) { if(i != 0) { #ifdef WIN32 classPath arrayItemValue = m_classPathArray->Get(i); if(!arrayItemValue->IsString()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Classpath must only contain strings"))); } v8::Local<:string> arrayItem = arrayItemValue->ToString(); v8::String::AsciiValue arrayItemStr(arrayItem); classPath v8NativeBindingLocation = handle_->Get(v8::String::New("nativeBindingLocation")); v8::String::AsciiValue nativeBindingLocationStr(v8NativeBindingLocation); s_nativeBindingLocation = *nativeBindingLocationStr; // get other options v8::Local<:value> optionsValue = handle_->Get(v8::String::New("options")); if(!optionsValue->IsArray()) { return ThrowException(v8::Exception::TypeError(v8::String::New("options must be an array"))); } v8::Local<:array> optionsArrayTemp = v8::Array::Cast(*optionsValue); m_optionsArray = v8::Persistent<:array>::New(optionsArrayTemp); // create vm options int vmOptionsCount = m_optionsArray->Length() + 1; JavaVMOption* vmOptions = new JavaVMOption[vmOptionsCount]; //printf("classPath: %s\n", classPath.str().c_str()); vmOptions[0].optionString = strdup(classPath.str().c_str()); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> arrayItemValue = m_optionsArray->Get(i); if(!arrayItemValue->IsString()) { delete[] vmOptions; return ThrowException(v8::Exception::TypeError(v8::String::New("options must only contain strings"))); } v8::Local<:string> arrayItem = arrayItemValue->ToString(); v8::String::AsciiValue arrayItemStr(arrayItem); vmOptions[i+1].optionString = strdup(*arrayItemStr); } JNI_GetDefaultJavaVMInitArgs(&args); args.version = JNI_VERSION_1_6; args.ignoreUnrecognized = false; args.options = vmOptions; args.nOptions = vmOptionsCount; JNI_CreateJavaVM(&jvmTemp, (void **)env, &args); *jvm = jvmTemp; m_classLoader = getSystemClassLoader(*env); // TODO: this handles sets put doesn't prevent modifing the underlying data. So java.classpath.push will still work which is invalid. handle_->SetAccessor(v8::String::New("classpath"), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); handle_->SetAccessor(v8::String::New("options"), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); handle_->SetAccessor(v8::String::New("nativeBindingLocation"), AccessorProhibitsOverwritingGetter, AccessorProhibitsOverwritingSetter); return v8::Undefined(); } /*static*/ v8::Handle<:value> Java::AccessorProhibitsOverwritingGetter(v8::Local<:string> name, const v8::AccessorInfo &info) { Java* self = node::ObjectWrap::Unwrap(info.This()); v8::HandleScope scope; v8::String::AsciiValue nameStr(name); if(!strcmp("classpath", *nameStr)) { return scope.Close(self->m_classPathArray); } else if(!strcmp("options", *nameStr)) { return scope.Close(self->m_optionsArray); } else if(!strcmp("nativeBindingLocation", *nameStr)) { return scope.Close(v8::String::New(Java::s_nativeBindingLocation.c_str())); } std::ostringstream errStr; errStr name, v8::Local<:value> value, const v8::AccessorInfo &info) { v8::String::AsciiValue nameStr(name); std::ostringstream errStr; errStr DestroyJavaVM(); *jvm = NULL; *env = NULL; } /*static*/ v8::Handle<:value> Java::getClassLoader(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); jclass classClazz = env->FindClass("java/lang/ClassLoader"); jmethodID class_getClassLoader = env->GetStaticMethodID(classClazz, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); jobject classLoader = env->CallStaticObjectMethod(classClazz, class_getClassLoader); checkJavaException(env); jobject result = env->NewGlobalRef(classLoader); return scope.Close(javaToV8(self, env, result)); } /*static*/ v8::Handle<:value> Java::newInstance(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; int argsEnd = args.Length(); // arguments ARGS_FRONT_CLASSNAME(); ARGS_BACK_CALLBACK(); // find class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { EXCEPTION_CALL_CALLBACK(self, "Could not find class " run(); END_CALLBACK_FUNCTION("\"Constructor for class '" Java::newInstanceSync(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; int argsEnd = args.Length(); // arguments ARGS_FRONT_CLASSNAME(); // find class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr callback = v8::Undefined(); NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); v8::Handle<:value> result = baton->runSync(); delete baton; if(result->IsNativeError()) { return ThrowException(result); } return scope.Close(result); } /*static*/ v8::Handle<:value> Java::newProxy(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; ARGS_FRONT_STRING(interfaceName); ARGS_FRONT_OBJECT(functions); DynamicProxyData* dynamicProxyData = new DynamicProxyData(); dynamicProxyData->markerStart = DYNAMIC_PROXY_DATA_MARKER_START; dynamicProxyData->markerEnd = DYNAMIC_PROXY_DATA_MARKER_END; dynamicProxyData->java = self; dynamicProxyData->interfaceName = interfaceName; dynamicProxyData->functions = v8::Persistent<:object>::New(functions); // find NodeDynamicProxyClass std::string className = "node.NodeDynamicProxyClass"; jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr FindClass("java/lang/Object"); jobjectArray methodArgs = env->NewObjectArray(2, objectClazz, NULL); env->SetObjectArrayElement(methodArgs, 0, v8ToJava(env, v8::String::New(s_nativeBindingLocation.c_str()))); env->SetObjectArrayElement(methodArgs, 1, longToJavaLongObj(env, (long)dynamicProxyData)); jobject method = javaFindConstructor(env, clazz, methodArgs); if(method == NULL) { std::ostringstream errStr; errStr callback = v8::Undefined(); NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); v8::Handle<:value> result = baton->runSync(); delete baton; if(result->IsNativeError()) { return ThrowException(result); } return scope.Close(result); } /*static*/ v8::Handle<:value> Java::callStaticMethod(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; int argsEnd = args.Length(); // arguments ARGS_FRONT_CLASSNAME(); ARGS_FRONT_STRING(methodName); ARGS_BACK_CALLBACK(); // find class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { EXCEPTION_CALL_CALLBACK(self, "Could not create class " run(); END_CALLBACK_FUNCTION("\"Static method '" Java::callStaticMethodSync(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; int argsEnd = args.Length(); // arguments ARGS_FRONT_CLASSNAME(); ARGS_FRONT_STRING(methodName); // find class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr callback = v8::Undefined(); StaticMethodCallBaton* baton = new StaticMethodCallBaton(self, clazz, method, methodArgs, callback); v8::Handle<:value> result = baton->runSync(); delete baton; if(result->IsNativeError()) { return ThrowException(result); } return scope.Close(result); } /*static*/ v8::Handle<:value> Java::findClassSync(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; // arguments ARGS_FRONT_CLASSNAME(); // find class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr result = javaToV8(self, env, clazz); return scope.Close(result); } /*static*/ v8::Handle<:value> Java::newArray(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; // arguments ARGS_FRONT_CLASSNAME(); // argument - array if(args.Length() IsArray()) { std::ostringstream errStr; errStr arrayObj = v8::Local<:array>::Cast(args[argsStart]); // find class and method jarray results; if(strcmp(className.c_str(), "byte") == 0) { results = env->NewByteArray(arrayObj->Length()); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> item = arrayObj->Get(i); jobject val = v8ToJava(env, item); jclass byteClazz = env->FindClass("java/lang/Byte"); jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B"); jbyte byteValues[1]; byteValues[0] = env->CallByteMethod(val, byte_byteValue); assert(!env->ExceptionCheck()); env->SetByteArrayRegion((jbyteArray)results, i, 1, byteValues); } } else if(strcmp(className.c_str(), "char") == 0) { results = env->NewCharArray(arrayObj->Length()); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> item = arrayObj->Get(i); jobject val = v8ToJava(env, item); jclass stringClazz = env->FindClass("java/lang/String"); jmethodID string_charAt = env->GetMethodID(stringClazz, "charAt", "(I)C"); jchar itemValues[1]; itemValues[0] = env->CallCharMethod(val, string_charAt, 0); checkJavaException(env); env->SetCharArrayRegion((jcharArray)results, i, 1, itemValues); } } else if(strcmp(className.c_str(), "short") == 0) { results = env->NewShortArray(arrayObj->Length()); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> item = arrayObj->Get(i); jobject val = v8ToJava(env, item); jclass shortClazz = env->FindClass("java/lang/Short"); jmethodID short_shortValue = env->GetMethodID(shortClazz, "shortValue", "()S"); jshort shortValues[1]; shortValues[0] = env->CallShortMethod(val, short_shortValue); assert(!env->ExceptionCheck()); env->SetShortArrayRegion((jshortArray)results, i, 1, shortValues); } } else if(strcmp(className.c_str(), "boolean") == 0) { results = env->NewBooleanArray(arrayObj->Length()); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> item = arrayObj->Get(i); jobject val = v8ToJava(env, item); jclass booleanClazz = env->FindClass("java/lang/Boolean"); jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z"); jboolean booleanValues[1]; booleanValues[0] = env->CallBooleanMethod(val, boolean_booleanValue); checkJavaException(env); env->SetBooleanArrayRegion((jbooleanArray)results, i, 1, booleanValues); } } else { jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr NewObjectArray(arrayObj->Length(), clazz, NULL); for(uint32_t i=0; iLength(); i++) { v8::Local<:value> item = arrayObj->Get(i); jobject val = v8ToJava(env, item); env->SetObjectArrayElement((jobjectArray)results, i, val); if(env->ExceptionOccurred()) { std::ostringstream errStr; v8::String::AsciiValue valStr(item); errStr Java::newByte(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newByte only takes 1 argument"))); } // argument - value if(!args[0]->IsNumber()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number"))); } v8::Local<:number> val = args[0]->ToNumber(); jclass clazz = env->FindClass("java/lang/Byte"); jmethodID constructor = env->GetMethodID(clazz, "", "(B)V"); jobject newObj = env->NewObject(clazz, constructor, (jbyte)val->Value()); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::newShort(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newShort only takes 1 argument"))); } // argument - value if(!args[0]->IsNumber()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number"))); } v8::Local<:number> val = args[0]->ToNumber(); jclass clazz = env->FindClass("java/lang/Short"); jmethodID constructor = env->GetMethodID(clazz, "", "(S)V"); jobject newObj = env->NewObject(clazz, constructor, (jshort)val->Value()); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::newLong(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newLong only takes 1 argument"))); } // argument - value if(!args[0]->IsNumber()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number"))); } v8::Local<:number> val = args[0]->ToNumber(); jclass clazz = env->FindClass("java/lang/Long"); jmethodID constructor = env->GetMethodID(clazz, "", "(J)V"); jobject newObj = env->NewObject(clazz, constructor, (jlong)val->Value()); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::newChar(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newChar only takes 1 argument"))); } // argument - value jchar charVal; if(args[0]->IsNumber()) { v8::Local<:number> val = args[0]->ToNumber(); charVal = (jchar)val->Value(); } else if(args[0]->IsString()) { v8::Local<:string> val = args[0]->ToString(); if(val->Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a string of 1 character."))); } std::string strVal = std::string(*v8::String::Utf8Value(val)); charVal = (jchar)strVal[0]; } else { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number or string"))); } jclass clazz = env->FindClass("java/lang/Character"); jmethodID constructor = env->GetMethodID(clazz, "", "(C)V"); jobject newObj = env->NewObject(clazz, constructor, charVal); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::newFloat(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newFloat only takes 1 argument"))); } else if(!args[0]->IsNumber()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number"))); } v8::Local<:number> val = args[0]->ToNumber(); jclass clazz = env->FindClass("java/lang/Float"); jmethodID constructor = env->GetMethodID(clazz, "", "(F)V"); jobject newObj = env->NewObject(clazz, constructor, (jfloat)val->Value()); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::newDouble(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); if(args.Length() != 1) { return ThrowException(v8::Exception::TypeError(v8::String::New("newDouble only takes 1 argument"))); } else if(!args[0]->IsNumber()) { return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a number"))); } v8::Local<:number> val = args[0]->ToNumber(); jclass clazz = env->FindClass("java/lang/Double"); jmethodID constructor = env->GetMethodID(clazz, "", "(D)V"); jobject newObj = env->NewObject(clazz, constructor, (jdouble)val->Value()); return scope.Close(JavaObject::New(self, newObj)); } /*static*/ v8::Handle<:value> Java::getStaticFieldValue(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; // arguments ARGS_FRONT_CLASSNAME(); ARGS_FRONT_STRING(fieldName); // find the class jclass clazz = javaFindClass(env, className); if(clazz == NULL) { std::ostringstream errStr; errStr FindClass("java/lang/reflect/Field"); jmethodID field_get = env->GetMethodID(fieldClazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); // get field value jobject val = env->CallObjectMethod(field, field_get, NULL); if(env->ExceptionOccurred()) { std::ostringstream errStr; errStr Java::setStaticFieldValue(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; // arguments ARGS_FRONT_CLASSNAME(); ARGS_FRONT_STRING(fieldName); // argument - new value if(args.Length() FindClass("java/lang/reflect/Field"); jmethodID field_set = env->GetMethodID(fieldClazz, "set", "(Ljava/lang/Object;Ljava/lang/Object;)V"); //printf("newValue: %s\n", javaObjectToString(env, newValue).c_str()); // set field value env->CallObjectMethod(field, field_set, NULL, newValue); if(env->ExceptionOccurred()) { std::ostringstream errStr; errStr Java::instanceOf(const v8::Arguments& args) { v8::HandleScope scope; Java* self = node::ObjectWrap::Unwrap(args.This()); v8::Handle<:value> ensureJvmResults = self->ensureJvm(); if(!ensureJvmResults->IsUndefined()) { return ensureJvmResults; } JNIEnv* env = self->getJavaEnv(); JavaScope javaScope(env); int argsStart = 0; ARGS_FRONT_OBJECT(obj); ARGS_FRONT_STRING(className); jobject instance = v8ToJava(env, obj); if (!instance) { // not even a Java object return v8::False(); } jclass clazz = javaFindClass(env, className); if(!clazz) { std::ostringstream errStr; errStr IsInstanceOf(instance, clazz); return v8::Boolean::New(res); } void EIO_CallJs(uv_work_t* req) { } #if NODE_MINOR_VERSION >= 10 void EIO_AfterCallJs(uv_work_t* req, int status) { #else void EIO_AfterCallJs(uv_work_t* req) { #endif DynamicProxyData* dynamicProxyData = static_cast(req->data); if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } dynamicProxyData->result = NULL; JNIEnv* env = dynamicProxyData->env; v8::HandleScope scope; v8::Array* v8Args; v8::Function* fn; v8::Handle<:value>* argv; int argc; int i; v8::Local<:value> v8Result; jobject javaResult; v8::Local<:value> fnObj = dynamicProxyData->functions->Get(v8::String::New(dynamicProxyData->methodName.c_str())); if(fnObj->IsUndefined() || fnObj->IsNull()) { printf("ERROR: Could not find method %s\n", dynamicProxyData->methodName.c_str()); goto CleanUp; } if(!fnObj->IsFunction()) { printf("ERROR: %s is not a function.\n", dynamicProxyData->methodName.c_str()); goto CleanUp; } fn = v8::Function::Cast(*fnObj); if(dynamicProxyData->args) { v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, dynamicProxyData->args)); argc = v8Args->Length(); } else { argc = 0; } argv = new v8::Handle<:value>[argc]; for(i=0; iGet(i); } v8Result = fn->Call(dynamicProxyData->functions, argc, argv); delete[] argv; if(!dynamicProxyDataVerify(dynamicProxyData)) { return; } javaResult = v8ToJava(env, v8Result); if(javaResult == NULL) { dynamicProxyData->result = NULL; dynamicProxyData->resultGlobalRef = NULL; } else { dynamicProxyData->result = javaResult; dynamicProxyData->resultGlobalRef = env->NewGlobalRef(javaResult); } CleanUp: dynamicProxyData->done = true; } JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jobject src, jlong ptr, jobject method, jobjectArray args) { long myThreadId = my_getThreadId(); DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; dynamicProxyData->env = env; dynamicProxyData->args = args; dynamicProxyData->done = false; dynamicProxyData->result = NULL; dynamicProxyData->resultGlobalRef = NULL; jclass methodClazz = env->FindClass("java/lang/reflect/Method"); jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;"); dynamicProxyData->methodName = javaObjectToString(env, env->CallObjectMethod(method, method_getName)); assert(!env->ExceptionCheck()); uv_work_t* req = new uv_work_t(); req->data = dynamicProxyData; if(myThreadId == v8ThreadId) { #if NODE_MINOR_VERSION >= 10 EIO_AfterCallJs(req, 0); #else EIO_AfterCallJs(req); #endif } else { uv_queue_work(uv_default_loop(), req, EIO_CallJs, (uv_after_work_cb)EIO_AfterCallJs); while(!dynamicProxyData->done) { my_sleep(100); } } if(!dynamicProxyDataVerify(dynamicProxyData)) { return NULL; } if(dynamicProxyData->result) { env->DeleteGlobalRef(dynamicProxyData->resultGlobalRef); } return dynamicProxyData->result; }