Beispiel #1
0
std::string methodNotFoundToString(JNIEnv *env, jclass clazz, std::string methodName, bool constructor, const v8::Arguments& args, int argStart, int argEnd) {
  std::ostringstream startOfMessage;
  std::ostringstream msg;

  jclass classClazz = env->FindClass("java/lang/Class");
  jmethodID class_getName = env->GetMethodID(classClazz, "getName", "()Ljava/lang/String;");

  startOfMessage << "Could not find method \"" << methodName.c_str() << "(";
  for(int i=argStart; i<argEnd; i++) {
    jobject val = v8ToJava(env, args[i]);
    if(i != argStart) {
      startOfMessage << ", ";
    }
    if(val == NULL) {
      startOfMessage << "(null)";
    } else {
      jclass argClass = env->GetObjectClass(val);
      jstring argClassNameJava = (jstring)env->CallObjectMethod(argClass, class_getName);
      std::string argClassName = javaToString(env, argClassNameJava);
      startOfMessage << argClassName;
    }
  }

  startOfMessage << ")\" on class \""<< javaObjectToString(env, clazz).c_str() << "\".";

  msg << startOfMessage.str() << " Possible matches:\n";

  jclass memberClazz = env->FindClass("java/lang/reflect/Member");
  jmethodID member_getName = env->GetMethodID(memberClazz, "getName", "()Ljava/lang/String;");

  std::list<jobject> methods;
  if(constructor) {
    javaReflectionGetConstructors(env, clazz, &methods);
  } else {
    javaReflectionGetMethods(env, clazz, &methods, true);
  }

  int count = 0;
  for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); ++it) {
    jstring methodNameTestJava = (jstring)env->CallObjectMethod(*it, member_getName);
    std::string methodNameTest = javaToString(env, methodNameTestJava);
    if(methodNameTest == methodName) {
      msg << "  " << javaObjectToString(env, *it).c_str() << "\n";
      count++;
    }
  }

  if(count == 0) {
    std::ostringstream noMethodsMsg;
    noMethodsMsg << startOfMessage.str() << " No methods with that name.";
    return noMethodsMsg.str();
  }

  return msg.str();
}
Beispiel #2
0
jvalueType javaGetType(JNIEnv *env, jclass type) {
  jclass clazzClazz = env->FindClass("java/lang/Class");
  jmethodID class_isArray = env->GetMethodID(clazzClazz, "isArray", "()Z");

  jboolean isArray = env->CallBooleanMethod(type, class_isArray);
  if(isArray) {
    return TYPE_ARRAY;
  } else {
    // TODO: has to be a better way
    std::string str = javaObjectToString(env, type);
    const char *typeStr = str.c_str();
    //printf("javaGetType: %s\n", typeStr);
    if(strcmp(typeStr, "void") == 0) {
      return TYPE_VOID;
    } else if(strcmp(typeStr, "int") == 0 || strcmp(typeStr, "class java.lang.Integer") == 0) {
      return TYPE_INT;
    } else if(strcmp(typeStr, "double") == 0 || strcmp(typeStr, "class java.lang.Double") == 0) {
      return TYPE_DOUBLE;
    } else if(strcmp(typeStr, "float") == 0 || strcmp(typeStr, "class java.lang.Float") == 0) {
      return TYPE_FLOAT;
    } else if(strcmp(typeStr, "long") == 0 || strcmp(typeStr, "class java.lang.Long") == 0) {
      return TYPE_LONG;
    } else if(strcmp(typeStr, "boolean") == 0 || strcmp(typeStr, "class java.lang.Boolean") == 0) {
      return TYPE_BOOLEAN;
    } else if(strcmp(typeStr, "short") == 0 || strcmp(typeStr, "class java.lang.Short") == 0) {
      return TYPE_SHORT;
    } else if(strcmp(typeStr, "byte") == 0 || strcmp(typeStr, "class java.lang.Byte") == 0) {
      return TYPE_BYTE;
    } else if(strcmp(typeStr, "class java.lang.String") == 0) {
      return TYPE_STRING;
    }
    return TYPE_OBJECT;
  }
}
Beispiel #3
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;
}
Beispiel #4
0
std::string javaMethodCallToString(JNIEnv *env, jobject obj, jmethodID methodId, jarray args) {
  char temp[100];

  std::ostringstream result;
  sprintf(temp, "%p", env);
  result << temp;
  result << ": ";
  result << javaObjectToString(env, obj);
  result << ": ";
  sprintf(temp, "%p", methodId);
  result << temp;
  result << ": (";
  jsize arraySize = env->GetArrayLength(args);
  for(int i=0; i<arraySize; i++) {
    if(i != 0) {
      result << ", ";
    }
    jobject arg = env->GetObjectArrayElement((jobjectArray)args, i);
    result << javaObjectToString(env, arg);
  }
  result << ")";

  return result.str();
}
Beispiel #5
0
std::string javaArrayToString(JNIEnv *env, jobjectArray arr) {
  if(arr == NULL) {
    return "(null)";
  }

  std::ostringstream result;
  result << "[";
  jsize count = env->GetArrayLength(arr);
  for(jsize i=0; i<count; i++) {
    if(i != 0) {
      result << ", ";
    }
    jobject obj = env->GetObjectArrayElement(arr, i);
    result << javaObjectToString(env, obj);
  }
  result << "]";
  return result.str();
}
Beispiel #6
0
v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) {
  v8::HandleScope scope;

  if(obj == NULL) {
    return v8::Null();
  }

  jclass objClazz = env->GetObjectClass(obj);
  jvalueType resultType = javaGetType(env, objClazz);

  //printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str());

  switch(resultType) {
    case TYPE_ARRAY:
      {
        v8::Handle<v8::Value> result = javaArrayToV8(java, env, (jobjectArray)obj);
        return scope.Close(result);
      }
    case TYPE_VOID:
      return v8::Undefined();
    case TYPE_BOOLEAN:
      {
        jclass booleanClazz = env->FindClass("java/lang/Boolean");
        jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z");
        bool result = env->CallBooleanMethod(obj, boolean_booleanValue);
        return scope.Close(v8::Boolean::New(result));
      }
    case TYPE_BYTE:
      {
        jclass byteClazz = env->FindClass("java/lang/Byte");
        jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B");
        jbyte result = env->CallByteMethod(obj, byte_byteValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_LONG:
      {
        jclass longClazz = env->FindClass("java/lang/Long");
        jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J");
        jlong result = env->CallLongMethod(obj, long_longValue);
        std::string strValue = javaObjectToString(env, obj);
        v8::Local<v8::Value> v8Result = v8::NumberObject::New(result);
        v8::NumberObject* v8ResultNumberObject = v8::NumberObject::Cast(*v8Result);
        v8ResultNumberObject->Set(v8::String::New("longValue"), v8::String::New(strValue.c_str()));
        v8ResultNumberObject->SetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_LONG), v8::Boolean::New(true));
        return scope.Close(v8Result);
      }
    case TYPE_INT:
      {
        jclass integerClazz = env->FindClass("java/lang/Integer");
        jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I");
        jint result = env->CallIntMethod(obj, integer_intValue);
        return scope.Close(v8::Integer::New(result));
      }
    case TYPE_SHORT:
      {
        jclass shortClazz = env->FindClass("java/lang/Short");
        jmethodID short_shortValue = env->GetMethodID(shortClazz, "shortValue", "()S");
        jshort result = env->CallShortMethod(obj, short_shortValue);
        return scope.Close(v8::Integer::New(result));
      }
    case TYPE_DOUBLE:
      {
        jclass doubleClazz = env->FindClass("java/lang/Double");
        jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D");
        jdouble result = env->CallDoubleMethod(obj, double_doubleValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_FLOAT:
      {
        jclass floatClazz = env->FindClass("java/lang/Float");
        jmethodID float_floatValue = env->GetMethodID(floatClazz, "floatValue", "()F");
        jfloat result = env->CallFloatMethod(obj, float_floatValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_STRING:
      return scope.Close(v8::String::New(javaObjectToString(env, obj).c_str()));
    case TYPE_OBJECT:
      return scope.Close(JavaObject::New(java, obj));
    default:
      printf("javaToV8: unhandled type: 0x%03x\n", resultType);
      return scope.Close(JavaObject::New(java, obj));
  }

  return v8::Undefined();
}
Beispiel #7
0
v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) {
  v8::HandleScope scope;

  if(obj == NULL) {
    return v8::Null();
  }

  jclass objClazz = env->GetObjectClass(obj);
  jvalueType resultType = javaGetType(env, objClazz);

  //printf("javaToV8: %d %s\n", resultType, javaObjectToString(env, obj).c_str());

  switch(resultType) {
    case TYPE_ARRAY:
      {
        v8::Handle<v8::Value> result = javaArrayToV8(java, env, (jobjectArray)obj);
        return scope.Close(result);
      }
    case TYPE_VOID:
      return v8::Undefined();
    case TYPE_BOOLEAN:
      {
        jclass booleanClazz = env->FindClass("java/lang/Boolean");
        jmethodID boolean_booleanValue = env->GetMethodID(booleanClazz, "booleanValue", "()Z");
        bool result = env->CallBooleanMethod(obj, boolean_booleanValue);
        return scope.Close(v8::Boolean::New(result));
      }
    case TYPE_BYTE:
      {
        jclass byteClazz = env->FindClass("java/lang/Byte");
        jmethodID byte_byteValue = env->GetMethodID(byteClazz, "byteValue", "()B");
        jbyte result = env->CallByteMethod(obj, byte_byteValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_LONG:
      {
        jclass longClazz = env->FindClass("java/lang/Long");
        jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J");
        jlong result = env->CallLongMethod(obj, long_longValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_INT:
      {
        jclass integerClazz = env->FindClass("java/lang/Integer");
        jmethodID integer_intValue = env->GetMethodID(integerClazz, "intValue", "()I");
        jint result = env->CallIntMethod(obj, integer_intValue);
        return scope.Close(v8::Integer::New(result));
      }
    case TYPE_DOUBLE:
      {
        jclass doubleClazz = env->FindClass("java/lang/Double");
        jmethodID double_doubleValue = env->GetMethodID(doubleClazz, "doubleValue", "()D");
        jdouble result = env->CallDoubleMethod(obj, double_doubleValue);
        return scope.Close(v8::Number::New(result));
      }
    case TYPE_STRING:
      return scope.Close(v8::String::New(javaObjectToString(env, obj).c_str()));
    case TYPE_OBJECT:
      return scope.Close(JavaObject::New(java, obj));
    default:
      printf("unhandled type: 0x%03x\n", resultType);
      return scope.Close(JavaObject::New(java, obj));
  }

  return v8::Undefined();
}
Beispiel #8
0
/*static*/ v8::Local<v8::Object> JavaObject::New(Java *java, jobject obj) {
  v8::HandleScope scope;

  JNIEnv *env = java->getJavaEnv();
  obj = env->NewGlobalRef(obj);
  JavaScope javaScope(env);

  jclass objClazz = env->GetObjectClass(obj);
  jclass classClazz = env->FindClass("java/lang/Class");
  jmethodID class_getName = env->GetMethodID(classClazz, "getName", "()Ljava/lang/String;");
  jobject classNameJava = env->CallObjectMethod(objClazz, class_getName);
  std::string className = javaObjectToString(env, classNameJava);
  std::replace(className.begin(), className.end(), '.', '_');
  std::replace(className.begin(), className.end(), '$', '_');
  std::replace(className.begin(), className.end(), '[', 'a');
  className = "nodeJava_" + className;

  v8::Persistent<v8::FunctionTemplate> persistentFuncTemplate;
  if(sFunctionTemplates.find(className) != sFunctionTemplates.end()) {
    //printf("existing className: %s\n", className.c_str());
    persistentFuncTemplate = sFunctionTemplates[className];
  } else {
    //printf("create className: %s\n", className.c_str());

    v8::Local<v8::FunctionTemplate> funcTemplate = v8::FunctionTemplate::New();
    funcTemplate->InstanceTemplate()->SetInternalFieldCount(1);
    funcTemplate->SetClassName(v8::String::NewSymbol(className.c_str()));

    std::list<jobject> methods;
    javaReflectionGetMethods(env, objClazz, &methods, false);
    jclass methodClazz = env->FindClass("java/lang/reflect/Method");
    jmethodID method_getName = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
    for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); it++) {
      jstring methodNameJava = (jstring)env->CallObjectMethod(*it, method_getName);
      std::string methodNameStr = javaToString(env, methodNameJava);

      v8::Handle<v8::String> methodName = v8::String::New(methodNameStr.c_str());
      v8::Local<v8::FunctionTemplate> methodCallTemplate = v8::FunctionTemplate::New(methodCall, methodName);
      funcTemplate->PrototypeTemplate()->Set(methodName, methodCallTemplate->GetFunction());

      v8::Handle<v8::String> methodNameSync = v8::String::New((methodNameStr + "Sync").c_str());
      v8::Local<v8::FunctionTemplate> methodCallSyncTemplate = v8::FunctionTemplate::New(methodCallSync, methodName);
      funcTemplate->PrototypeTemplate()->Set(methodNameSync, methodCallSyncTemplate->GetFunction());
    }

    std::list<jobject> fields;
    javaReflectionGetFields(env, objClazz, &fields);
    jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
    jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;");
    for(std::list<jobject>::iterator it = fields.begin(); it != fields.end(); it++) {
      jstring fieldNameJava = (jstring)env->CallObjectMethod(*it, field_getName);
      std::string fieldNameStr = javaToString(env, fieldNameJava);

      v8::Handle<v8::String> fieldName = v8::String::New(fieldNameStr.c_str());
      funcTemplate->InstanceTemplate()->SetAccessor(fieldName, fieldGetter, fieldSetter);
    }

    sFunctionTemplates[className] = persistentFuncTemplate = v8::Persistent<v8::FunctionTemplate>::New(funcTemplate);
  }

  v8::Local<v8::Function> ctor = persistentFuncTemplate->GetFunction();
  v8::Local<v8::Object> javaObjectObj = ctor->NewInstance();
  javaObjectObj->SetHiddenValue(v8::String::New("__isJavaObject"), v8::Boolean::New(true));
  JavaObject *self = new JavaObject(java, obj);
  self->Wrap(javaObjectObj);

  return scope.Close(javaObjectObj);
}