Skip to content

Commit 4b7bc21

Browse files
committed
better java long handling
1 parent 6e7709e commit 4b7bc21

4 files changed

Lines changed: 93 additions & 57 deletions

File tree

src/javaObject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

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

src/utils.cpp

Lines changed: 80 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
#define MODIFIER_STATIC 9
1010

11+
jobject v8ToJava_javaObject(JNIEnv* env, v8::Local<v8::Object> obj);
12+
jobject v8ToJava_javaLong(JNIEnv* env, v8::Local<v8::Object> obj);
13+
1114
void javaReflectionGetMethods(JNIEnv *env, jclass clazz, std::list<jobject>* methods, bool includeStatic) {
1215
jclass clazzclazz = env->FindClass("java/lang/Class");
1316
jmethodID clazz_getMethods = env->GetMethodID(clazzclazz, "getMethods", "()[Ljava/lang/reflect/Method;");
@@ -267,55 +270,15 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
267270

268271
if(arg->IsObject()) {
269272
v8::Local<v8::Object> obj = v8::Object::Cast(*arg);
270-
v8::Local<v8::Value> isJavaObject = obj->GetHiddenValue(v8::String::New("__isJavaObject"));
273+
274+
v8::Local<v8::Value> isJavaObject = obj->GetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_OBJECT));
271275
if(!isJavaObject.IsEmpty() && isJavaObject->IsBoolean()) {
272-
JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj);
273-
jobject jobj = javaObject->getObject();
274-
275-
jclass nodeDynamicProxyClass = env->FindClass("node/NodeDynamicProxyClass");
276-
if(env->IsInstanceOf(jobj, nodeDynamicProxyClass)) {
277-
jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
278-
DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(jobj, ptrField);
279-
if(!dynamicProxyDataVerify(proxyData)) {
280-
return NULL;
281-
}
282-
283-
jclass dynamicInterface = javaFindClass(env, proxyData->interfaceName);
284-
if(dynamicInterface == NULL) {
285-
printf("Could not find interface %s\n", proxyData->interfaceName.c_str());
286-
return NULL;
287-
}
288-
jclass classClazz = env->FindClass("java/lang/Class");
289-
jobjectArray classArray = env->NewObjectArray(1, classClazz, NULL);
290-
env->SetObjectArrayElement(classArray, 0, dynamicInterface);
291-
292-
jmethodID class_getClassLoader = env->GetMethodID(classClazz, "getClassLoader", "()Ljava/lang/ClassLoader;");
293-
jobject classLoader = env->CallObjectMethod(dynamicInterface, class_getClassLoader);
294-
if(classLoader == NULL) {
295-
jclass objectClazz = env->FindClass("java/lang/Object");
296-
jmethodID object_getClass = env->GetMethodID(objectClazz, "getClass", "()Ljava/lang/Class;");
297-
jobject jobjClass = env->CallObjectMethod(jobj, object_getClass);
298-
classLoader = env->CallObjectMethod(jobjClass, class_getClassLoader);
299-
}
300-
301-
jclass proxyClass = env->FindClass("java/lang/reflect/Proxy");
302-
jmethodID proxy_newProxyInstance = env->GetStaticMethodID(proxyClass, "newProxyInstance", "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;");
303-
if(classLoader == NULL) {
304-
printf("Could not get classloader for Proxy\n");
305-
return NULL;
306-
}
307-
if(classArray == NULL) {
308-
printf("Could not create class array for Proxy\n");
309-
return NULL;
310-
}
311-
if(jobj == NULL) {
312-
printf("Not a valid object to wrap\n");
313-
return NULL;
314-
}
315-
jobj = env->CallStaticObjectMethod(proxyClass, proxy_newProxyInstance, classLoader, classArray, jobj);
316-
}
276+
return v8ToJava_javaObject(env, obj);
277+
}
317278

318-
return jobj;
279+
v8::Local<v8::Value> isJavaLong = obj->GetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_LONG));
280+
if(!isJavaLong.IsEmpty() && isJavaLong->IsBoolean()) {
281+
return v8ToJava_javaLong(env, obj);
319282
}
320283
}
321284

@@ -325,6 +288,64 @@ jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg) {
325288
return NULL;
326289
}
327290

291+
jobject v8ToJava_javaObject(JNIEnv* env, v8::Local<v8::Object> obj) {
292+
JavaObject* javaObject = node::ObjectWrap::Unwrap<JavaObject>(obj);
293+
jobject jobj = javaObject->getObject();
294+
295+
jclass nodeDynamicProxyClass = env->FindClass("node/NodeDynamicProxyClass");
296+
if(env->IsInstanceOf(jobj, nodeDynamicProxyClass)) {
297+
jfieldID ptrField = env->GetFieldID(nodeDynamicProxyClass, "ptr", "J");
298+
DynamicProxyData* proxyData = (DynamicProxyData*)(long)env->GetLongField(jobj, ptrField);
299+
if(!dynamicProxyDataVerify(proxyData)) {
300+
return NULL;
301+
}
302+
303+
jclass dynamicInterface = javaFindClass(env, proxyData->interfaceName);
304+
if(dynamicInterface == NULL) {
305+
printf("Could not find interface %s\n", proxyData->interfaceName.c_str());
306+
return NULL;
307+
}
308+
jclass classClazz = env->FindClass("java/lang/Class");
309+
jobjectArray classArray = env->NewObjectArray(1, classClazz, NULL);
310+
env->SetObjectArrayElement(classArray, 0, dynamicInterface);
311+
312+
jmethodID class_getClassLoader = env->GetMethodID(classClazz, "getClassLoader", "()Ljava/lang/ClassLoader;");
313+
jobject classLoader = env->CallObjectMethod(dynamicInterface, class_getClassLoader);
314+
if(classLoader == NULL) {
315+
jclass objectClazz = env->FindClass("java/lang/Object");
316+
jmethodID object_getClass = env->GetMethodID(objectClazz, "getClass", "()Ljava/lang/Class;");
317+
jobject jobjClass = env->CallObjectMethod(jobj, object_getClass);
318+
classLoader = env->CallObjectMethod(jobjClass, class_getClassLoader);
319+
}
320+
321+
jclass proxyClass = env->FindClass("java/lang/reflect/Proxy");
322+
jmethodID proxy_newProxyInstance = env->GetStaticMethodID(proxyClass, "newProxyInstance", "(Ljava/lang/ClassLoader;[Ljava/lang/Class;Ljava/lang/reflect/InvocationHandler;)Ljava/lang/Object;");
323+
if(classLoader == NULL) {
324+
printf("Could not get classloader for Proxy\n");
325+
return NULL;
326+
}
327+
if(classArray == NULL) {
328+
printf("Could not create class array for Proxy\n");
329+
return NULL;
330+
}
331+
if(jobj == NULL) {
332+
printf("Not a valid object to wrap\n");
333+
return NULL;
334+
}
335+
jobj = env->CallStaticObjectMethod(proxyClass, proxy_newProxyInstance, classLoader, classArray, jobj);
336+
}
337+
338+
return jobj;
339+
}
340+
341+
jobject v8ToJava_javaLong(JNIEnv* env, v8::Local<v8::Object> obj) {
342+
jobject longValue = v8ToJava(env, obj->Get(v8::String::New("longValue")));
343+
jclass longClazz = env->FindClass("java/lang/Long");
344+
jmethodID long_constructor = env->GetMethodID(longClazz, "<init>", "(Ljava/lang/String;)V");
345+
jobject jobj = env->NewObject(longClazz, long_constructor, longValue);
346+
return jobj;
347+
}
348+
328349
jobjectArray v8ToJava(JNIEnv* env, const v8::Arguments& args, int start, int end) {
329350
jclass clazz = env->FindClass("java/lang/Object");
330351
jobjectArray results = env->NewObjectArray(end-start, clazz, NULL);
@@ -429,14 +450,18 @@ v8::Handle<v8::Value> javaToV8(Java* java, JNIEnv* env, jobject obj) {
429450
jbyte result = env->CallByteMethod(obj, byte_byteValue);
430451
return scope.Close(v8::Number::New(result));
431452
}
432-
// Removed to support long return types and long parameters.
433-
// case TYPE_LONG:
434-
// {
435-
// jclass longClazz = env->FindClass("java/lang/Long");
436-
// jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J");
437-
// jlong result = env->CallLongMethod(obj, long_longValue);
438-
// return scope.Close(v8::Number::New(result));
439-
// }
453+
case TYPE_LONG:
454+
{
455+
jclass longClazz = env->FindClass("java/lang/Long");
456+
jmethodID long_longValue = env->GetMethodID(longClazz, "longValue", "()J");
457+
jlong result = env->CallLongMethod(obj, long_longValue);
458+
std::string strValue = javaObjectToString(env, obj);
459+
v8::Local<v8::Value> v8Result = v8::NumberObject::New(result);
460+
v8::NumberObject* v8ResultNumberObject = v8::NumberObject::Cast(*v8Result);
461+
v8ResultNumberObject->Set(v8::String::New("longValue"), v8::String::New(strValue.c_str()));
462+
v8ResultNumberObject->SetHiddenValue(v8::String::New(V8_HIDDEN_MARKER_JAVA_LONG), v8::Boolean::New(true));
463+
return scope.Close(v8Result);
464+
}
440465
case TYPE_INT:
441466
{
442467
jclass integerClazz = env->FindClass("java/lang/Integer");

src/utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212

1313
class Java;
1414

15+
#define V8_HIDDEN_MARKER_JAVA_LONG "__isJavaLong"
16+
#define V8_HIDDEN_MARKER_JAVA_OBJECT "__isJavaObject"
17+
1518
typedef enum _jvalueType {
1619
TYPE_VOID = 1,
1720
TYPE_INT = 2,

test/java-callStaticMethod-test.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ exports['Java - Call Static Method'] = nodeunit.testCase({
143143
});
144144
},
145145

146+
"java.lang.Long addition": function(test) {
147+
var javaLong = java.newInstanceSync("java.lang.Long", 5);
148+
test.equal(javaLong.toString(), '5');
149+
var result = javaLong + 1;
150+
test.equal(result, 6);
151+
test.done();
152+
},
153+
146154
"java.lang.Long calls (java Long)": function(test) {
147155
var javaLong = java.newInstanceSync("java.lang.Long", 5);
148156
java.callStaticMethod("Test", "staticMethodLongToString", javaLong, function(err, result) {
@@ -161,7 +169,7 @@ exports['Java - Call Static Method'] = nodeunit.testCase({
161169
return test.done(err);
162170
}
163171
test.ok(result);
164-
test.equal(result.toStringSync(), "9223372036854775807");
172+
test.equal(result.longValue, "9223372036854775807");
165173
test.done();
166174
});
167175
}

0 commit comments

Comments
 (0)