Skip to content

Commit ffefa98

Browse files
committed
initial method argument decoding
1 parent 91daf0e commit ffefa98

7 files changed

Lines changed: 75 additions & 38 deletions

File tree

src/java.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ Java::~Java() {
5353
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
5454
JNIEnv* env = self->getJavaEnv();
5555

56+
int argsEnd = args.Length();
57+
5658
// argument - className
5759
if(args.Length() < 1 || !args[0]->IsString()) {
5860
return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 0 must be a string")));
@@ -64,15 +66,18 @@ Java::~Java() {
6466
// argument - callback
6567
v8::Handle<v8::Value> callback;
6668
if(args[args.Length()-1]->IsFunction()) {
67-
callback = args[args.Length()-1];
69+
callback = args[argsEnd-1];
70+
argsEnd--;
6871
} else {
6972
callback = v8::Null();
7073
}
7174

72-
std::list<jobject> methodArgs; // TODO: build args
75+
std::list<int> methodArgTypes;
76+
jarray methodArgs = v8ToJava(env, args, 1, argsEnd, &methodArgTypes);
77+
7378
jclass clazz = javaFindClass(env, className);
7479
std::list<jobject> constructors = javaReflectionGetConstructors(env, clazz);
75-
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgs);
80+
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgTypes);
7681

7782
// run
7883
NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback);
@@ -86,6 +91,8 @@ Java::~Java() {
8691
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
8792
JNIEnv* env = self->getJavaEnv();
8893

94+
int argsEnd = args.Length();
95+
8996
// argument - className
9097
if(args.Length() < 1 || !args[0]->IsString()) {
9198
return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 0 must be a string")));
@@ -94,10 +101,12 @@ Java::~Java() {
94101
v8::String::AsciiValue classNameVal(classNameObj);
95102
std::string className = *classNameVal;
96103

97-
std::list<jobject> methodArgs; // TODO: build args
104+
std::list<int> methodArgTypes;
105+
jarray methodArgs = v8ToJava(env, args, 1, argsEnd, &methodArgTypes);
106+
98107
jclass clazz = javaFindClass(env, className);
99108
std::list<jobject> constructors = javaReflectionGetConstructors(env, clazz);
100-
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgs);
109+
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgTypes);
101110

102111
// run
103112
v8::Handle<v8::Value> callback = v8::Object::New();

src/javaObject.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,21 @@ JavaObject::~JavaObject() {
6060

6161
v8::String::AsciiValue methodName(args.Data());
6262

63-
int argsLength = args.Length();
63+
int argsEnd = args.Length();
6464

6565
// argument - callback
6666
v8::Handle<v8::Value> callback;
6767
if(args[args.Length()-1]->IsFunction()) {
68-
callback = args[argsLength-1];
69-
argsLength--;
68+
callback = args[argsEnd-1];
69+
argsEnd--;
7070
} else {
7171
callback = v8::Null();
7272
}
7373

74-
std::list<jobject> methodArgs; // TODO: build args
74+
std::list<int> methodArgTypes;
75+
jarray methodArgs = v8ToJava(env, args, 0, argsEnd, &methodArgTypes);
7576

76-
jobject method = javaFindBestMatchingMethod(env, self->m_methods, *methodName, methodArgs);
77+
jobject method = javaFindBestMatchingMethod(env, self->m_methods, *methodName, methodArgTypes);
7778
if(method == NULL) {
7879
return v8::Undefined(); // TODO: callback with error
7980
}
@@ -92,9 +93,10 @@ JavaObject::~JavaObject() {
9293

9394
v8::String::AsciiValue methodName(args.Data());
9495

95-
std::list<jobject> methodArgs; // TODO: build args
96+
std::list<int> methodArgTypes;
97+
jarray methodArgs = v8ToJava(env, args, 0, args.Length(), &methodArgTypes);
9698

97-
jobject method = javaFindBestMatchingMethod(env, self->m_methods, *methodName, methodArgs);
99+
jobject method = javaFindBestMatchingMethod(env, self->m_methods, *methodName, methodArgTypes);
98100
if(method == NULL) {
99101
return v8::Undefined();
100102
}

src/methodCallBaton.cpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@
33
#include "java.h"
44
#include "javaObject.h"
55

6-
MethodCallBaton::MethodCallBaton(Java* java, jobject method, std::list<jobject>& args, v8::Handle<v8::Value>& callback) {
6+
MethodCallBaton::MethodCallBaton(Java* java, jobject method, jarray args, v8::Handle<v8::Value>& callback) {
77
JNIEnv *env = java->getJavaEnv();
88

99
m_java = java;
10-
for(std::list<jobject>::iterator it = args.begin(); it != args.end(); it++) {
11-
m_args.push_back(env->NewGlobalRef(*it));
12-
}
10+
m_args = (jarray)env->NewGlobalRef(args);
1311
m_callback = v8::Persistent<v8::Value>::New(callback);
1412
m_method = env->NewGlobalRef(method);
1513
}
1614

1715
MethodCallBaton::~MethodCallBaton() {
1816
JNIEnv *env = m_java->getJavaEnv();
19-
for(std::list<jobject>::iterator it = m_args.begin(); it != m_args.end(); it++) {
20-
env->DeleteGlobalRef(*it);
21-
}
22-
17+
env->DeleteGlobalRef(m_args);
2318
env->DeleteGlobalRef(m_method);
2419
m_callback.Dispose();
2520
}
@@ -83,9 +78,7 @@ void NewInstanceBaton::execute(JNIEnv *env) {
8378
jclass constructorClazz = env->FindClass("java/lang/reflect/Constructor");
8479
jmethodID constructor_newInstance = env->GetMethodID(constructorClazz, "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
8580

86-
jclass objectClazz = env->FindClass("java/lang/Object");
87-
jobjectArray parameters = env->NewObjectArray(0, objectClazz, NULL); // TODO: init parameters
88-
jobject result = env->CallObjectMethod(m_method, constructor_newInstance, parameters);
81+
jobject result = env->CallObjectMethod(m_method, constructor_newInstance, m_args);
8982
m_resultType = TYPE_OBJECT;
9083
m_result = env->NewGlobalRef(result);
9184
if(env->ExceptionCheck()) {
@@ -101,10 +94,8 @@ void InstanceMethodCallBaton::execute(JNIEnv *env) {
10194

10295
jclass returnType = (jclass)env->CallObjectMethod(m_method, method_getReturnType);
10396

104-
jclass objectClazz = env->FindClass("java/lang/Object");
105-
jobjectArray parameters = env->NewObjectArray(0, objectClazz, NULL); // TODO: init parameters
10697
m_resultType = javaGetType(env, returnType);
107-
jobject result = env->CallObjectMethod(m_method, method_invoke, m_javaObject->getObject(), parameters);
98+
jobject result = env->CallObjectMethod(m_method, method_invoke, m_javaObject->getObject(), m_args);
10899
m_result = env->NewGlobalRef(result);
109100
if(env->ExceptionCheck()) {
110101
env->ExceptionDescribe(); // TODO: handle error
@@ -116,7 +107,7 @@ NewInstanceBaton::NewInstanceBaton(
116107
Java* java,
117108
jclass clazz,
118109
jobject method,
119-
std::list<jobject>& args,
110+
jarray args,
120111
v8::Handle<v8::Value>& callback) : MethodCallBaton(java, method, args, callback) {
121112
JNIEnv *env = m_java->getJavaEnv();
122113
m_clazz = (jclass)env->NewGlobalRef(clazz);
@@ -131,7 +122,7 @@ InstanceMethodCallBaton::InstanceMethodCallBaton(
131122
Java* java,
132123
JavaObject* obj,
133124
jobject method,
134-
std::list<jobject>& args,
125+
jarray args,
135126
v8::Handle<v8::Value>& callback) : MethodCallBaton(java, method, args, callback) {
136127
m_javaObject = obj;
137128
m_javaObject->Ref();

src/methodCallBaton.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class JavaObject;
1313

1414
class MethodCallBaton {
1515
public:
16-
MethodCallBaton(Java* java, jobject method, std::list<jobject>& args, v8::Handle<v8::Value>& callback);
16+
MethodCallBaton(Java* java, jobject method, jarray args, v8::Handle<v8::Value>& callback);
1717
virtual ~MethodCallBaton();
1818

1919
static void EIO_MethodCall(eio_req* req);
@@ -28,15 +28,15 @@ class MethodCallBaton {
2828

2929
Java* m_java;
3030
v8::Persistent<v8::Value> m_callback;
31-
std::list<jobject> m_args;
31+
jarray m_args;
3232
jobject m_result;
3333
jobject m_method;
3434
int m_resultType;
3535
};
3636

3737
class InstanceMethodCallBaton : public MethodCallBaton {
3838
public:
39-
InstanceMethodCallBaton(Java* java, JavaObject* obj, jobject method, std::list<jobject>& args, v8::Handle<v8::Value>& callback);
39+
InstanceMethodCallBaton(Java* java, JavaObject* obj, jobject method, jarray args, v8::Handle<v8::Value>& callback);
4040
virtual ~InstanceMethodCallBaton();
4141

4242
protected:
@@ -47,7 +47,7 @@ class InstanceMethodCallBaton : public MethodCallBaton {
4747

4848
class NewInstanceBaton : public MethodCallBaton {
4949
public:
50-
NewInstanceBaton(Java* java, jclass clazz, jobject method, std::list<jobject>& args, v8::Handle<v8::Value>& callback);
50+
NewInstanceBaton(Java* java, jclass clazz, jobject method, jarray args, v8::Handle<v8::Value>& callback);
5151
virtual ~NewInstanceBaton();
5252

5353
protected:

src/utils.cpp

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,19 @@ jobject javaFindBestMatchingMethod(
5454
JNIEnv *env,
5555
std::list<jobject>& methods,
5656
const char *methodName,
57-
std::list<jobject>& args) {
57+
std::list<int>& argTypes) {
5858

5959
jclass methodClazz = env->FindClass("java/lang/reflect/Method");
6060
jmethodID method_getNameMethod = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
61+
jmethodID method_getParameterTypes = env->GetMethodID(methodClazz, "getParameterTypes", "()[Ljava/lang/Class;");
6162

6263
for(std::list<jobject>::iterator it = methods.begin(); it != methods.end(); it++) {
6364
std::string itMethodName = javaToString(env, (jstring)env->CallObjectMethod(*it, method_getNameMethod));
6465
if(itMethodName == methodName) {
65-
return *it; // TODO: check parameters
66+
jarray parameters = (jarray)env->CallObjectMethod(*it, method_getParameterTypes);
67+
if(env->GetArrayLength(parameters) == (jsize)argTypes.size()) {
68+
return *it; // TODO: check parameters
69+
}
6670
}
6771
}
6872
return NULL;
@@ -71,14 +75,14 @@ jobject javaFindBestMatchingMethod(
7175
jobject javaFindBestMatchingConstructor(
7276
JNIEnv *env,
7377
std::list<jobject>& constructors,
74-
std::list<jobject>& args) {
78+
std::list<int>& argTypes) {
7579

7680
jclass constructorClazz = env->FindClass("java/lang/reflect/Constructor");
7781
jmethodID constructor_getParameterTypes = env->GetMethodID(constructorClazz, "getParameterTypes", "()[Ljava/lang/Class;");
7882

7983
for(std::list<jobject>::iterator it = constructors.begin(); it != constructors.end(); it++) {
8084
jarray parameters = (jarray)env->CallObjectMethod(*it, constructor_getParameterTypes);
81-
if(env->GetArrayLength(parameters) == (jsize)args.size()) {
85+
if(env->GetArrayLength(parameters) == (jsize)argTypes.size()) {
8286
return *it; // TODO: check parameters
8387
}
8488
}
@@ -123,3 +127,27 @@ jclass javaFindClass(JNIEnv* env, std::string className) {
123127
return clazz;
124128
}
125129

130+
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg, int *methodArgType) {
131+
if(arg->IsString()) {
132+
v8::String::AsciiValue val(arg->ToString());
133+
return env->NewStringUTF(*val);
134+
} else {
135+
return NULL;
136+
}
137+
}
138+
139+
jarray v8ToJava(JNIEnv* env, const v8::Arguments& args, int start, int end, std::list<int> *methodArgTypes) {
140+
jclass clazz = env->FindClass("java/lang/Object");
141+
jobjectArray results = env->NewObjectArray(end-start, clazz, NULL);
142+
143+
for(int i=start; i<end; i++) {
144+
int methodArgType;
145+
jobject val = v8ToJava(env, args[i], &methodArgType);
146+
env->SetObjectArrayElement(results, i, val);
147+
if(methodArgTypes) {
148+
methodArgTypes->push_back(methodArgType);
149+
}
150+
}
151+
152+
return results;
153+
}

src/utils.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#ifndef _utils_h_
33
#define _utils_h_
44

5+
#include <v8.h>
56
#include <jni.h>
67
#include <list>
78
#include <string>
@@ -20,14 +21,16 @@ jobject javaFindBestMatchingMethod(
2021
JNIEnv *env,
2122
std::list<jobject>& methods,
2223
const char *methodName,
23-
std::list<jobject>& args);
24+
std::list<int>& argTypes);
2425
jobject javaFindBestMatchingConstructor(
2526
JNIEnv *env,
2627
std::list<jobject>& constructors,
27-
std::list<jobject>& args);
28+
std::list<int>& argTypes);
2829
JNIEnv* javaAttachCurrentThread(JavaVM* jvm);
2930
void javaDetachCurrentThread(JavaVM* jvm);
3031
jvalueType javaGetType(JNIEnv *env, jclass type);
3132
jclass javaFindClass(JNIEnv* env, std::string className);
33+
jarray v8ToJava(JNIEnv* env, const v8::Arguments& args, int start, int end, std::list<int> *methodArgTypes);
34+
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg, int *methodArgType);
3235

3336
#endif

test/simple-test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ exports['Simple'] = nodeunit.testCase({
2424

2525
"create an instance of a class and call methods (getName) (sync)": function(test) {
2626
var list = java.newInstanceSync("java.util.ArrayList");
27+
test.equal(list.sizeSync(), 0);
28+
list.addSync("hello");
29+
list.addSync("world");
30+
test.equal(list.sizeSync(), 2);
2731
var clazz = list.getClassSync();
2832
var result = clazz.getNameSync();
2933
test.equal(result, "java.util.ArrayList");

0 commit comments

Comments
 (0)