#include "javaObject.h"
#include "java.h"
#include "utils.h"
#include
/*static*/ v8::Persistent<:functiontemplate> JavaObject::s_ct;
/*static*/ void JavaObject::Init(v8::Handle<:object> target) {
v8::HandleScope scope;
v8::Local<:functiontemplate> t = v8::FunctionTemplate::New();
s_ct = v8::Persistent<:functiontemplate>::New(t);
s_ct->InstanceTemplate()->SetInternalFieldCount(1);
s_ct->SetClassName(v8::String::NewSymbol("JavaObject"));
target->Set(v8::String::NewSymbol("JavaObject"), s_ct->GetFunction());
}
/*static*/ v8::Local<:object> JavaObject::New(Java *java, jobject obj) {
v8::HandleScope scope;
JNIEnv *env = java->getJavaEnv();
PUSH_LOCAL_JAVA_FRAME();
v8::Local<:function> ctor = s_ct->GetFunction();
v8::Local<:object> javaObjectObj = ctor->NewInstance();
JavaObject *self = new JavaObject(java, obj);
self->Wrap(javaObjectObj);
std::list methods;
javaReflectionGetMethods(env, self->m_class, &methods);
jclass methodClazz = env->FindClass("java/lang/reflect/Method");
jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
for(std::list::iterator it = methods.begin(); it != methods.end(); it++) {
jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName);
std::string methodNameStr = javaToString(env, methodNameJava);
v8::Handle<:string> methodName = v8::String::New(methodNameStr.c_str());
v8::Local<:functiontemplate> methodCallTemplate = v8::FunctionTemplate::New(methodCall, methodName);
javaObjectObj->Set(methodName, methodCallTemplate->GetFunction());
v8::Handle<:string> methodNameSync = v8::String::New((methodNameStr + "Sync").c_str());
v8::Local<:functiontemplate> methodCallSyncTemplate = v8::FunctionTemplate::New(methodCallSync, methodName);
javaObjectObj->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
env->DeleteLocalRef(methodNameJava);
env->DeleteLocalRef(*it);
}
std::list fields;
javaReflectionGetFields(env, self->m_class, &fields);
jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;");
for(std::list::iterator it = fields.begin(); it != fields.end(); it++) {
jstring fieldNameJava = (jstring)env->CallObjectMethod(*it, field_getName);
std::string fieldNameStr = javaToString(env, fieldNameJava);
v8::Handle<:string> fieldName = v8::String::New(fieldNameStr.c_str());
javaObjectObj->SetAccessor(fieldName, fieldGetter, fieldSetter);
env->DeleteLocalRef(fieldNameJava);
env->DeleteLocalRef(*it);
}
env->DeleteLocalRef(obj);
POP_LOCAL_JAVA_FRAME();
return scope.Close(javaObjectObj);
}
JavaObject::JavaObject(Java *java, jobject obj) {
m_java = java;
JNIEnv *env = m_java->getJavaEnv();
m_obj = env->NewGlobalRef(obj);
m_class = (jclass)env->NewGlobalRef(env->GetObjectClass(obj));
}
JavaObject::~JavaObject() {
JNIEnv *env = m_java->getJavaEnv();
jclass nodeDynamicProxyClass = env->FindClass("node/NodeDynamicProxyClass");
if(env->IsInstanceOf(m_obj, nodeDynamicProxyClass)) {
jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(m_obj, ptrField);
if(dynamicProxyDataVerify(proxyData)) {
delete proxyData;
}
}
env->DeleteGlobalRef(m_obj);
env->DeleteGlobalRef(m_class);
}
/*static*/ v8::Handle<:value> JavaObject::methodCall(const v8::Arguments& args) {
v8::HandleScope scope;
JavaObject* self = node::ObjectWrap::Unwrap(args.This());
JNIEnv *env = self->m_java->getJavaEnv();
PUSH_LOCAL_JAVA_FRAME();
v8::String::AsciiValue methodName(args.Data());
std::string methodNameStr = *methodName;
int argsStart = 0;
int argsEnd = args.Length();
// arguments
ARGS_BACK_CALLBACK();
if(!callbackProvided && methodNameStr == "toString") {
POP_LOCAL_JAVA_FRAME();
return methodCallSync(args);
}
jobjectArray methodArgs = v8ToJava(env, args, argsStart, argsEnd);
jobject method = javaFindMethod(env, self->m_class, methodNameStr, methodArgs);
if(method == NULL) {
EXCEPTION_CALL_CALLBACK("Could not find method " m_java, self, method, methodArgs, callback);
baton->run();
env->DeleteLocalRef(methodArgs);
env->DeleteLocalRef(method);
POP_LOCAL_JAVA_FRAME();
END_CALLBACK_FUNCTION("\"Method '" JavaObject::methodCallSync(const v8::Arguments& args) {
v8::HandleScope scope;
JavaObject* self = node::ObjectWrap::Unwrap(args.This());
JNIEnv *env = self->m_java->getJavaEnv();
PUSH_LOCAL_JAVA_FRAME();
v8::String::AsciiValue methodName(args.Data());
std::string methodNameStr = *methodName;
int argsStart = 0;
int argsEnd = args.Length();
jobjectArray methodArgs = v8ToJava(env, args, argsStart, argsEnd);
jobject method = javaFindMethod(env, self->m_class, methodNameStr, methodArgs);
if(method == NULL) {
std::ostringstream errStr;
errStr ex = javaExceptionToV8(env, errStr.str());
POP_LOCAL_JAVA_FRAME();
return ThrowException(ex);
}
// run
v8::Handle<:value> callback = v8::Object::New();
InstanceMethodCallBaton* baton = new InstanceMethodCallBaton(self->m_java, self, method, methodArgs, callback);
v8::Handle<:value> result = baton->runSync();
delete baton;
POP_LOCAL_JAVA_FRAME();
return scope.Close(result);
}
/*static*/ v8::Handle<:value> JavaObject::fieldGetter(v8::Local<:string> property, const v8::AccessorInfo& info) {
v8::HandleScope scope;
JavaObject* self = node::ObjectWrap::Unwrap(info.This());
JNIEnv *env = self->m_java->getJavaEnv();
PUSH_LOCAL_JAVA_FRAME();
v8::String::AsciiValue propertyCStr(property);
std::string propertyStr = *propertyCStr;
jobject field = javaFindField(env, self->m_class, propertyStr);
if(field == NULL) {
std::ostringstream errStr;
errStr ex = javaExceptionToV8(env, errStr.str());
POP_LOCAL_JAVA_FRAME();
return ThrowException(ex);
}
jclass fieldClazz = env->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, self->m_obj);
if(env->ExceptionOccurred()) {
std::ostringstream errStr;
errStr ex = javaExceptionToV8(env, errStr.str());
POP_LOCAL_JAVA_FRAME();
return ThrowException(ex);
}
v8::Handle<:value> result = javaToV8(self->m_java, env, val);
env->DeleteLocalRef(fieldClazz);
env->DeleteLocalRef(field);
env->DeleteLocalRef(val);
POP_LOCAL_JAVA_FRAME();
return scope.Close(result);
}
/*static*/ void JavaObject::fieldSetter(v8::Local<:string> property, v8::Local<:value> value, const v8::AccessorInfo& info) {
v8::HandleScope scope;
JavaObject* self = node::ObjectWrap::Unwrap(info.This());
JNIEnv *env = self->m_java->getJavaEnv();
PUSH_LOCAL_JAVA_FRAME();
jobject newValue = v8ToJava(env, value);
v8::String::AsciiValue propertyCStr(property);
std::string propertyStr = *propertyCStr;
jobject field = javaFindField(env, self->m_class, propertyStr);
if(field == NULL) {
std::ostringstream errStr;
errStr ex = javaExceptionToV8(env, errStr.str());
POP_LOCAL_JAVA_FRAME();
ThrowException(ex);
return;
}
jclass fieldClazz = env->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, self->m_obj, newValue);
if(env->ExceptionOccurred()) {
std::ostringstream errStr;
errStr ex = javaExceptionToV8(env, errStr.str());
POP_LOCAL_JAVA_FRAME();
ThrowException(ex);
return;
}
POP_LOCAL_JAVA_FRAME();
}