Esempio n. 1
0
JNIEXPORT jobject JNICALL Java_node_NodeDynamicProxyClass_callJs(JNIEnv *env, jobject src, jlong ptr, jobject method, jobjectArray args) {
  threadId myThreadId = my_getThreadId();

  bool hasArgsGlobalRef = false;

  // args needs to be global, you can't send env across thread boundaries
  DynamicProxyData* dynamicProxyData = (DynamicProxyData*)ptr;
  dynamicProxyData->args = args;
  dynamicProxyData->done = false;
  dynamicProxyData->result = NULL;
  dynamicProxyData->throwableClass = "";
  dynamicProxyData->throwableMessage = "";

  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));
  assertNoException(env);

  uv_work_t* req = new uv_work_t();
  req->data = dynamicProxyData;
  if(v8ThreadIdEquals(myThreadId, v8ThreadId)) {
#if NODE_MINOR_VERSION >= 10
    EIO_AfterCallJs(req, 0);
#else
    EIO_AfterCallJs(req);
#endif
  } else {
    if (args) {
      // if args is not null and we have to kick this across the thread boundary, make it a global ref
      dynamicProxyData->args = (jobjectArray) env->NewGlobalRef(args);
      hasArgsGlobalRef = true;
    }

    uv_queue_work(uv_default_loop(), req, EIO_CallJs, (uv_after_work_cb)EIO_AfterCallJs);

    while(!dynamicProxyData->done) {
      my_sleep(100);
    }
  }

  if(!dynamicProxyDataVerify(dynamicProxyData)) {
    throwNewThrowable(env, "java/lang/IllegalStateException", "dynamicProxyData was corrupted");
  }
  if(hasArgsGlobalRef) {
    env->DeleteGlobalRef(dynamicProxyData->args);
  }

  if (dynamicProxyData->done == DYNAMIC_PROXY_JS_ERROR) {
    throwNewThrowable(env, dynamicProxyData->throwableClass.c_str(), dynamicProxyData->throwableMessage);
  }

  jobject result = NULL;
  if(dynamicProxyData->result) {
    // need to retain a local ref so that we can return it, otherwise the returned object gets corrupted
    result = env->NewLocalRef(dynamicProxyData->result);
    env->DeleteGlobalRef(dynamicProxyData->result);
  }
  return result;
}
Esempio n. 2
0
jobject v8ToJava_javaObject(JNIEnv* env, v8::Local<v8::Object> obj) {
  JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj);
  jobject jobj = javaObject->getObject();

  jclass nodeDynamicProxyClass = env->FindClass("node/NodeDynamicProxyClass");
  if(env->IsInstanceOf(jobj, nodeDynamicProxyClass)) {
    jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
    DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(jobj, ptrField);
    if(!dynamicProxyDataVerify(proxyData)) {
      return NULL;
    }

    jclass dynamicInterface = javaFindClass(env, proxyData->interfaceName);
    if(dynamicInterface == NULL) {
      printf("Could not find interface %s\n", proxyData->interfaceName.c_str());
      return NULL;
    }
    jclass classClazz = env->FindClass("java/lang/Class");
    jobjectArray classArray = env->NewObjectArray(1, classClazz, NULL);
    env->SetObjectArrayElement(classArray, 0, dynamicInterface);

    jmethodID class_getClassLoader = env->GetMethodID(classClazz, "getClassLoader", "()Ljava/lang/ClassLoader;");
    jobject classLoader = env->CallObjectMethod(dynamicInterface, class_getClassLoader);
    if(classLoader == NULL) {
      jclass objectClazz = env->FindClass("java/lang/Object");
      jmethodID object_getClass = env->GetMethodID(objectClazz, "getClass", "()Ljava/lang/Class;");
      jobject jobjClass = env->CallObjectMethod(jobj, object_getClass);
      classLoader = env->CallObjectMethod(jobjClass, class_getClassLoader);
    }

    jclass proxyClass = env->FindClass("java/lang/reflect/Proxy");
    jmethodID proxy_newProxyInstance = env->GetStaticMethodID(proxyClass, "newProxyInstance", "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;");
    if(classLoader == NULL) {
      printf("Could not get classloader for Proxy\n");
      return NULL;
    }
    if(classArray == NULL) {
      printf("Could not create class array for Proxy\n");
      return NULL;
    }
    if(jobj == NULL) {
      printf("Not a valid object to wrap\n");
      return NULL;
    }
    jobj = env->CallStaticObjectMethod(proxyClass, proxy_newProxyInstance, classLoader, classArray, jobj);
  }

  return jobj;
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
void EIO_AfterCallJs(uv_work_t* req, int status) {
#else
void EIO_AfterCallJs(uv_work_t* req) {
#endif
  DynamicProxyData* dynamicProxyData = static_cast<DynamicProxyData*>(req->data);
  if(!dynamicProxyDataVerify(dynamicProxyData)) {
    return;
  }
  dynamicProxyData->result = NULL;

  JNIEnv* env;
  int ret = dynamicProxyData->java->getJvm()->GetEnv((void**)&env, JNI_BEST_VERSION);
  if (ret != JNI_OK) {
    dynamicProxyData->throwableClass = "java/lang/IllegalStateException";
    dynamicProxyData->throwableMessage = "Could not retrieve JNIEnv: jvm->GetEnv returned " + to_string<int>(ret);
    dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR;
    return;
  }

  Nan::HandleScope scope;
  v8::Array* v8Args;
  v8::Function* fn;
  v8::Handle<v8::Value>* argv;
  int argc;
  int i;
  v8::Local<v8::Value> v8Result;
  jobject javaResult;

  v8::Local<v8::Object> dynamicProxyDataFunctions = Nan::New(dynamicProxyData->functions);
  v8::Local<v8::Value> fnObj = dynamicProxyDataFunctions->Get(Nan::New<v8::String>(dynamicProxyData->methodName.c_str()).ToLocalChecked());
  if(fnObj->IsUndefined() || fnObj->IsNull()) {
    dynamicProxyData->throwableClass = "java/lang/NoSuchMethodError";
    dynamicProxyData->throwableMessage = "Could not find js function " + dynamicProxyData->methodName;
    dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR;
    return;
  }
  if(!fnObj->IsFunction()) {
    dynamicProxyData->throwableClass = "java/lang/IllegalStateException";
    dynamicProxyData->throwableMessage = dynamicProxyData->methodName + " is not a function";
    dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR;
    return;
  }

  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<v8::Value>[argc];
  for(i=0; i<argc; i++) {
    argv[i] = v8Args->Get(i);
  }

  Nan::TryCatch tryCatch;
  tryCatch.SetCaptureMessage(true);
  v8Result = fn->Call(dynamicProxyDataFunctions, argc, argv);
  delete[] argv;
  if (tryCatch.HasCaught()) {
    dynamicProxyData->throwableClass = "node/NodeJsException";
    v8::String::Utf8Value message(tryCatch.Message()->Get());
    dynamicProxyData->throwableMessage = std::string(*message);
    tryCatch.Reset();
    dynamicProxyData->done = DYNAMIC_PROXY_JS_ERROR;
    return;
  }

  if(!dynamicProxyDataVerify(dynamicProxyData)) {
    return;
  }

  javaResult = v8ToJava(env, v8Result);
  if(javaResult == NULL) {
    dynamicProxyData->result = NULL;
  } else {
    dynamicProxyData->result = env->NewGlobalRef(javaResult);
  }

  dynamicProxyData->done = true;
}