#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;
}