|
3 | 3 | #include <string.h> |
4 | 4 | #include "javaObject.h" |
5 | 5 | #include "methodCallBaton.h" |
| 6 | +#include "node_NodeDynamicProxyClass.h" |
6 | 7 | #include <sstream> |
7 | 8 |
|
8 | 9 | /*static*/ v8::Persistent<v8::FunctionTemplate> Java::s_ct; |
|
17 | 18 |
|
18 | 19 | NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstance", newInstance); |
19 | 20 | NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstanceSync", newInstanceSync); |
| 21 | + NODE_SET_PROTOTYPE_METHOD(s_ct, "newDynamicProxy", newDynamicProxy); |
20 | 22 | NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethod", callStaticMethod); |
21 | 23 | NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethodSync", callStaticMethodSync); |
22 | 24 | NODE_SET_PROTOTYPE_METHOD(s_ct, "findClassSync", findClassSync); |
@@ -86,14 +88,14 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) { |
86 | 88 | v8::String::AsciiValue arrayItemStr(arrayItem); |
87 | 89 | classPath << *arrayItemStr; |
88 | 90 | } |
89 | | - |
| 91 | + |
90 | 92 | // get other options |
91 | 93 | v8::Local<v8::Value> optionsValue = handle_->Get(v8::String::New("options")); |
92 | 94 | if(!optionsValue->IsArray()) { |
93 | 95 | return ThrowException(v8::Exception::TypeError(v8::String::New("options must be an array"))); |
94 | 96 | } |
95 | 97 | v8::Local<v8::Array> optionsArray = v8::Array::Cast(*optionsValue); |
96 | | - |
| 98 | + |
97 | 99 | // create vm options |
98 | 100 | int vmOptionsCount = optionsArray->Length() + 1; |
99 | 101 | JavaVMOption* vmOptions = new JavaVMOption[vmOptionsCount]; |
@@ -200,6 +202,57 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) { |
200 | 202 | return scope.Close(result); |
201 | 203 | } |
202 | 204 |
|
| 205 | +/*static*/ v8::Handle<v8::Value> Java::newDynamicProxy(const v8::Arguments& args) { |
| 206 | + v8::HandleScope scope; |
| 207 | + Java* self = node::ObjectWrap::Unwrap<Java>(args.This()); |
| 208 | + v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm(); |
| 209 | + if(!ensureJvmResults->IsUndefined()) { |
| 210 | + return ensureJvmResults; |
| 211 | + } |
| 212 | + JNIEnv* env = self->getJavaEnv(); |
| 213 | + |
| 214 | + int argsStart = 0; |
| 215 | + int argsEnd = args.Length(); |
| 216 | + |
| 217 | + ARGS_FRONT_STRING(interfaceName); |
| 218 | + ARGS_FRONT_OBJECT(functions); |
| 219 | + |
| 220 | + DynamicProxyData* dynamicProxyData = new DynamicProxyData(); |
| 221 | + dynamicProxyData->java = self; |
| 222 | + dynamicProxyData->interfaceName = interfaceName; |
| 223 | + dynamicProxyData->functions = v8::Persistent<v8::Object>::New(functions); |
| 224 | + |
| 225 | + // find NodeDynamicProxyClass |
| 226 | + std::string className = "node.NodeDynamicProxyClass"; |
| 227 | + jclass clazz = javaFindClass(env, className); |
| 228 | + if(clazz == NULL) { |
| 229 | + std::ostringstream errStr; |
| 230 | + errStr << "Could not create class node/NodeDynamicProxyClass"; |
| 231 | + return ThrowException(javaExceptionToV8(env, errStr.str())); |
| 232 | + } |
| 233 | + |
| 234 | + // find constructor |
| 235 | + jclass objectClazz = env->FindClass("java/lang/Integer"); |
| 236 | + jobjectArray methodArgs = env->NewObjectArray(1, objectClazz, NULL); |
| 237 | + env->SetObjectArrayElement(methodArgs, 0, v8ToJava(env, v8::Integer::New((int)dynamicProxyData))); |
| 238 | + jobject method = javaFindConstructor(env, clazz, methodArgs); |
| 239 | + if(method == NULL) { |
| 240 | + std::ostringstream errStr; |
| 241 | + errStr << "Could not find constructor"; |
| 242 | + return ThrowException(javaExceptionToV8(env, errStr.str())); |
| 243 | + } |
| 244 | + |
| 245 | + // run constructor |
| 246 | + v8::Handle<v8::Value> callback = v8::Object::New(); |
| 247 | + NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback); |
| 248 | + v8::Handle<v8::Value> result = baton->runSync(); |
| 249 | + delete baton; |
| 250 | + if(result->IsNativeError()) { |
| 251 | + return ThrowException(result); |
| 252 | + } |
| 253 | + return scope.Close(result); |
| 254 | +} |
| 255 | + |
203 | 256 | /*static*/ v8::Handle<v8::Value> Java::callStaticMethod(const v8::Arguments& args) { |
204 | 257 | v8::HandleScope scope; |
205 | 258 | Java* self = node::ObjectWrap::Unwrap<Java>(args.This()); |
@@ -511,3 +564,32 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) { |
511 | 564 |
|
512 | 565 | return v8::Undefined(); |
513 | 566 | } |
| 567 | + |
| 568 | +JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jobject src, jint ptr, jobject method, jobjectArray args) { |
| 569 | + v8::HandleScope scope; |
| 570 | + |
| 571 | + DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr; |
| 572 | + jclass methodClazz = env->FindClass("java/lang/reflect/Method"); |
| 573 | + jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;"); |
| 574 | + std::string methodName = javaObjectToString(env, env->CallObjectMethod(method, method_getName)); |
| 575 | + |
| 576 | + v8::Local<v8::Value> fnObj = dynamicProxyData->functions->Get(v8::String::New(methodName.c_str())); |
| 577 | + if(fnObj->IsUndefined() || fnObj->IsNull()) { |
| 578 | + printf("ERROR: Could not find method %s", methodName.c_str()); |
| 579 | + } |
| 580 | + if(!fnObj->IsFunction()) { |
| 581 | + printf("ERROR: %s is not a function.", methodName.c_str()); |
| 582 | + } |
| 583 | + v8::Function* fn = v8::Function::Cast(*fnObj); |
| 584 | + |
| 585 | + v8::Array* v8Args = v8::Array::Cast(*javaArrayToV8(dynamicProxyData->java, env, args)); |
| 586 | + int argc = v8Args->Length(); |
| 587 | + v8::Handle<v8::Value>* argv = new v8::Handle<v8::Value>[argc]; |
| 588 | + for(int i=0; i<argc; i++) { |
| 589 | + argv[i] = v8Args->Get(i); |
| 590 | + } |
| 591 | + v8::Local<v8::Value> result = fn->Call(dynamicProxyData->functions, argc, argv); |
| 592 | + delete[] argv; |
| 593 | + |
| 594 | + return v8ToJava(env, result); |
| 595 | +} |
0 commit comments