Пример #1
0
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
  if(arg->IsNull() || arg->IsUndefined()) {
    return NULL;
  }

  if(arg->IsArray()) {
    v8::Local<v8::Array> array = v8::Array::Cast(*arg);
    uint32_t arraySize = array->Length();
    jclass objectClazz = env->FindClass("java/lang/Object");
    jobjectArray result = env->NewObjectArray(arraySize, objectClazz, NULL);
    for(uint32_t i=0; i<arraySize; i++) {
      jobject val = v8ToJava(env, array->Get(i));
      env->SetObjectArrayElement(result, i, val);
    }
    return result;
  }

  if(arg->IsString()) {
    v8::String::AsciiValue val(arg->ToString());
    return env->NewStringUTF(*val);
  }

  if(arg->IsInt32() || arg->IsUint32()) {
    jint val = arg->ToInt32()->Value();
    jclass clazz = env->FindClass("java/lang/Integer");
    jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V");
    return env->NewObject(clazz, constructor, val);
  }

  if(arg->IsNumber()) {
    jdouble val = arg->ToNumber()->Value();
    jclass clazz = env->FindClass("java/lang/Double");
    jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V");
    return env->NewObject(clazz, constructor, val);
  }

  if(arg->IsBoolean()) {
    jboolean val = arg->ToBoolean()->Value();
    jclass clazz = env->FindClass("java/lang/Boolean");
    jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V");
    return env->NewObject(clazz, constructor, val);
  }

  if(arg->IsObject()) {
    v8::Local<v8::Object> obj = v8::Object::Cast(*arg);
    v8::String::AsciiValue constructorName(obj->GetConstructorName());
    if(strcmp(*constructorName, "JavaObject") == 0) {
      JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj);
      return javaObject->getObject();
    }
  }

  // TODO: handle other arg types
  v8::String::AsciiValue typeStr(arg);
  printf("Unhandled type: %s\n", *typeStr);
  return NULL;
}
Пример #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;
}
JNIEXPORT void JNICALL
Java_org_appcelerator_kroll_runtime_v8_V8Object_nativeRelease
	(JNIEnv *env, jclass clazz, jlong refPointer)
{
	ENTER_V8(V8Runtime::globalContext);
	JNIScope jniScope(env);

	if (refPointer) {
		Persistent<Object> handle((Object *)refPointer);
		JavaObject *javaObject = NativeObject::Unwrap<JavaObject>(handle);
		if (javaObject && javaObject->isDetached()) {
			delete javaObject;
		}
	}
}
Пример #4
0
// converts js value to java object and recursively converts sub objects if this
// object is a container type
jobject TypeConverter::jsValueToJavaObject(v8::Local<v8::Value> jsValue, bool *isNew)
{
	JNIEnv *env = JNIScope::getEnv();
	if (env == NULL) {
		return NULL;
	}

	if (jsValue->IsNumber()) {
		jdouble javaDouble = TypeConverter::jsNumberToJavaDouble(jsValue->ToNumber());
		*isNew = true;
		return env->NewObject(JNIUtil::doubleClass, JNIUtil::doubleInitMethod, javaDouble);

	} else if (jsValue->IsBoolean()) {
		jboolean javaBoolean = TypeConverter::jsBooleanToJavaBoolean(jsValue->ToBoolean());
		*isNew = true;
		return env->NewObject(JNIUtil::booleanClass, JNIUtil::booleanInitMethod, javaBoolean);

	} else if (jsValue->IsString()) {
		*isNew = true;
		return TypeConverter::jsStringToJavaString(jsValue->ToString());

	} else if (jsValue->IsDate()) {
		Local<Date> date = Local<Date>::Cast<Value>(jsValue);
		return TypeConverter::jsDateToJavaDate(date);

	} else if (jsValue->IsArray()) {
		*isNew = true;
		return TypeConverter::jsArrayToJavaArray(v8::Handle<v8::Array>::Cast(jsValue));

	} else if (jsValue->IsFunction()) {
		*isNew = true;
		return TypeConverter::jsObjectToJavaFunction(jsValue->ToObject());

	} else if (jsValue->IsObject()) {
		v8::Handle<v8::Object> jsObject = jsValue->ToObject();

		if (JavaObject::isJavaObject(jsObject)) {
			*isNew = JavaObject::useGlobalRefs ? false : true;
			JavaObject *javaObject = JavaObject::Unwrap<JavaObject>(jsObject);
			return javaObject->getJavaObject();
		} else {
			v8::Handle<v8::Array> objectKeys = jsObject->GetOwnPropertyNames();
			int numKeys = objectKeys->Length();
			*isNew = true;
			jobject javaHashMap = env->NewObject(JNIUtil::hashMapClass, JNIUtil::hashMapInitMethod, numKeys);

			for (int i = 0; i < numKeys; i++) {
				v8::Local<v8::Value> jsObjectPropertyKey = objectKeys->Get((uint32_t) i);
				bool keyIsNew, valueIsNew;
				jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(jsObjectPropertyKey, &keyIsNew);
				v8::Local<v8::Value> jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey);
				jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(jsObjectPropertyValue, &valueIsNew);

				jobject result = env->CallObjectMethod(javaHashMap,
				                                       JNIUtil::hashMapPutMethod,
				                                       javaObjectPropertyKey,
				                                       javaObjectPropertyValue);
				env->DeleteLocalRef(result);

				if (keyIsNew) {
					env->DeleteLocalRef(javaObjectPropertyKey);
				}
				if (valueIsNew) {
					env->DeleteLocalRef(javaObjectPropertyValue);
				}
			}

			return javaHashMap;
		}
	}

	LOGW(TAG, "jsValueToJavaObject returning null");
	return NULL;
}
Пример #5
0
// Callback for V8 letting us know the JavaScript object is no longer reachable.
// Once we receive this callback we can safely release our strong reference
// on the wrapped Java object so it can become eligible for collection.
static void DetachCallback(const v8::WeakCallbackData<v8::Object, JavaObject>& data)
{
	JavaObject* javaObject = data.GetParameter();
	javaObject->detach();
}
v8::Handle<v8::Value> TypeConverter::javaObjectToJsValue(JNIEnv *env, jobject javaObject)
{
	if (!javaObject) {
		return v8::Null();
	}

	if (env->IsInstanceOf(javaObject, JNIUtil::booleanClass)) {
		jboolean javaBoolean = env->CallBooleanMethod(javaObject, JNIUtil::booleanBooleanValueMethod);
		return javaBoolean ? v8::True() : v8::False();

	} else if (env->IsInstanceOf(javaObject, JNIUtil::numberClass)) {
		jdouble javaDouble = env->CallDoubleMethod(javaObject, JNIUtil::numberDoubleValueMethod);
		return v8::Number::New((double) javaDouble);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::stringClass)) {
		return TypeConverter::javaStringToJsString(env, (jstring) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::dateClass)) {
		return TypeConverter::javaDateToJsDate(env, javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::hashMapClass)) {
		return TypeConverter::javaHashMapToJsValue(env, javaObject);
	} else if (env->IsInstanceOf(javaObject, JNIUtil::krollProxyClass)) {
		jobject krollObject = env->GetObjectField(javaObject, JNIUtil::krollProxyKrollObjectField);
		if (krollObject) {
			jlong v8ObjectPointer = env->GetLongField(krollObject, JNIUtil::v8ObjectPtrField);
			env->DeleteLocalRef(krollObject);

			if (v8ObjectPointer != 0) {
				Persistent<Object> v8Object = Persistent<Object>((Object *) v8ObjectPointer);
				JavaObject *jo = NativeObject::Unwrap<JavaObject>(v8Object);
				jobject javaProxy = jo->getJavaObject(); // Called to explicitly go from weak reference to strong!
				if (!JavaObject::useGlobalRefs) {
					// But then we need to delete the local reference to avoid JNI ref leak!
					env->DeleteLocalRef(javaProxy);
				}
				return v8Object;
			}
		}

		jclass javaObjectClass = env->GetObjectClass(javaObject);
		v8::Handle<v8::Object> proxyHandle = ProxyFactory::createV8Proxy(javaObjectClass, javaObject);
		env->DeleteLocalRef(javaObjectClass);
		return proxyHandle;

	} else if (env->IsInstanceOf(javaObject, JNIUtil::v8FunctionClass)) {
		return javaObjectToJsFunction(javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::objectArrayClass)) {
		return javaArrayToJsArray((jobjectArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::shortArrayClass)) {
		return javaArrayToJsArray((jshortArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::intArrayClass)) {
		return javaArrayToJsArray((jintArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::longArrayClass)) {
		return javaArrayToJsArray((jlongArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::floatArrayClass)) {
		return javaArrayToJsArray((jfloatArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::doubleArrayClass)) {
		return javaArrayToJsArray((jdoubleArray) javaObject);

	} else if (env->IsInstanceOf(javaObject, JNIUtil::booleanArrayClass)) {
		return javaArrayToJsArray((jbooleanArray) javaObject);

	} else if (env->IsSameObject(JNIUtil::undefinedObject, javaObject)) {
		return v8::Undefined();
	}

	jclass javaObjectClass = env->GetObjectClass(javaObject);
	JNIUtil::logClassName("!!! Unable to convert unknown Java object class '%s' to JS value !!!", javaObjectClass, true);
	env->DeleteLocalRef(javaObjectClass);

	return v8::Handle<v8::Value>();
}
jobject TypeConverter::jsValueToJavaObject(JNIEnv *env, v8::Local<v8::Value> jsValue, bool *isNew)
{
	if (jsValue->IsNumber()) {
		*isNew = true;
		if (jsValue->IsInt32()) {
			jint javaInt = TypeConverter::jsNumberToJavaInt(jsValue->ToNumber());
			return env->NewObject(JNIUtil::integerClass, JNIUtil::integerInitMethod, javaInt);
		}
		jdouble javaDouble = TypeConverter::jsNumberToJavaDouble(jsValue->ToNumber());
		return env->NewObject(JNIUtil::doubleClass, JNIUtil::doubleInitMethod, javaDouble);

	} else if (jsValue->IsBoolean()) {
		jboolean javaBoolean = TypeConverter::jsBooleanToJavaBoolean(jsValue->ToBoolean());
		*isNew = true;
		return env->NewObject(JNIUtil::booleanClass, JNIUtil::booleanInitMethod, javaBoolean);

	} else if (jsValue->IsString()) {
		*isNew = true;
		return TypeConverter::jsStringToJavaString(env, jsValue->ToString());

	} else if (jsValue->IsDate()) {
		Local<Date> date = Local<Date>::Cast<Value>(jsValue);
		return TypeConverter::jsDateToJavaDate(env, date);

	} else if (jsValue->IsArray()) {
		*isNew = true;
		return TypeConverter::jsArrayToJavaArray(env, v8::Handle<v8::Array>::Cast(jsValue));

	} else if (jsValue->IsFunction()) {
		*isNew = true;
		return TypeConverter::jsObjectToJavaFunction(env, jsValue->ToObject());

	} else if (jsValue->IsObject()) {
		v8::Handle<v8::Object> jsObject = jsValue->ToObject();
		if (JavaObject::isJavaObject(jsObject)) {
			*isNew = JavaObject::useGlobalRefs ? false : true;
			JavaObject *javaObject = JavaObject::Unwrap<JavaObject>(jsObject);
			return javaObject->getJavaObject();
		} else {
			// Unwrap hyperloop JS wrappers to get native java proxy
			Handle<String> nativeString = String::New("$native");
			if (jsObject->HasOwnProperty(nativeString)) {
				v8::Local<v8::Value> nativeObject = jsObject->GetRealNamedProperty(nativeString);
				jsObject = nativeObject->ToObject();
				if (JavaObject::isJavaObject(jsObject)) {
					*isNew = JavaObject::useGlobalRefs ? false : true;
					JavaObject *javaObject = JavaObject::Unwrap<JavaObject>(jsObject);
					return javaObject->getJavaObject();
				}
			}

			v8::Handle<v8::Array> objectKeys = jsObject->GetOwnPropertyNames();
			int numKeys = objectKeys->Length();
			*isNew = true;
			jobject javaHashMap = env->NewObject(JNIUtil::hashMapClass, JNIUtil::hashMapInitMethod, numKeys);

			for (int i = 0; i < numKeys; i++) {
				v8::Local<v8::Value> jsObjectPropertyKey = objectKeys->Get((uint32_t) i);
				bool keyIsNew, valueIsNew;
				jobject javaObjectPropertyKey = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyKey, &keyIsNew);
				v8::Local<v8::Value> jsObjectPropertyValue = jsObject->Get(jsObjectPropertyKey);
				jobject javaObjectPropertyValue = TypeConverter::jsValueToJavaObject(env, jsObjectPropertyValue, &valueIsNew);

				jobject result = env->CallObjectMethod(javaHashMap,
				                                       JNIUtil::hashMapPutMethod,
				                                       javaObjectPropertyKey,
				                                       javaObjectPropertyValue);
				env->DeleteLocalRef(result);

				if (keyIsNew) {
					env->DeleteLocalRef(javaObjectPropertyKey);
				}
				if (valueIsNew) {
					env->DeleteLocalRef(javaObjectPropertyValue);
				}
			}

			return javaHashMap;
		}
	}

	if (!jsValue->IsNull() && !jsValue->IsUndefined()) {
		LOGW(TAG, "jsValueToJavaObject returning null.");
	}
	return NULL;
}
Пример #8
0
// Callback for V8 letting us know the JavaScript object is no longer reachable.
// Once we receive this callback we can safely release our strong reference
// on the wrapped Java object so it can become eligible for collection.
static void DetachCallback(v8::Persistent<v8::Value> value, void *data)
{
	JavaObject *javaObject = static_cast<JavaObject*>(data);
	javaObject->detach();
}
Пример #9
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);
}