Skip to content

Commit 6a69278

Browse files
committed
add static field get. added lucene example
1 parent ee8db2e commit 6a69278

7 files changed

Lines changed: 213 additions & 5 deletions

File tree

examples/lucene/example.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/usr/bin/env node
2+
3+
var java = require("../../");
4+
java.classpath.push("lucene-core-3.5.0.jar");
5+
6+
var idx = java.newInstanceSync("org.apache.lucene.store.RAMDirectory");
7+
var version = java.getStaticFieldValue("org.apache.lucene.util.Version", "LUCENE_CURRENT");
8+
var analyzer = java.newInstanceSync("org.apache.lucene.analysis.standard.StandardAnalyzer", version);
9+
var writerConfig = java.newInstanceSync("org.apache.lucene.index.IndexWriterConfig", version, analyzer);
10+
var writer = java.newInstanceSync("org.apache.lucene.index.IndexWriter", idx, writerConfig);
11+
12+
writer.addDocumentSync(createDocument("Theodore Roosevelt",
13+
"It behooves every man to remember that the work of the " +
14+
"critic, is of altogether secondary importance, and that, " +
15+
"in the end, progress is accomplished by the man who does " +
16+
"things."));
17+
writer.addDocumentSync(createDocument("Friedrich Hayek",
18+
"The case for individual freedom rests largely on the " +
19+
"recognition of the inevitable and universal ignorance " +
20+
"of all of us concerning a great many of the factors on " +
21+
"which the achievements of our ends and welfare depend."));
22+
writer.addDocumentSync(createDocument("Ayn Rand",
23+
"There is nothing to take a man's freedom away from " +
24+
"him, save other men. To be free, a man must be free " +
25+
"of his brothers."));
26+
writer.addDocumentSync(createDocument("Mohandas Gandhi",
27+
"Freedom is not worth having if it does not connote " +
28+
"freedom to err."));
29+
30+
writer.closeSync();
31+
32+
var searcher = java.newInstanceSync("org.apache.lucene.search.IndexSearcher", idx);
33+
34+
search(searcher, "freedom");
35+
search(searcher, "free");
36+
search(searcher, "progress or achievements");
37+
38+
searcher.closeSync();
39+
40+
function createDocument(title, content) {
41+
var fieldStoreYes = java.callStaticMethodSync("org.apache.lucene.document.Field$Store", "valueOf", "YES");
42+
var fieldIndexAnalyzed = java.callStaticMethodSync("org.apache.lucene.document.Field$Index", "valueOf", "ANALYZED");
43+
var doc = java.newInstanceSync("org.apache.lucene.document.Document");
44+
doc.addSync(java.newInstanceSync("org.apache.lucene.document.Field", "title", title, fieldStoreYes, fieldIndexAnalyzed));
45+
doc.addSync(java.newInstanceSync("org.apache.lucene.document.Field", "content", content, fieldStoreYes, fieldIndexAnalyzed));
46+
return doc;
47+
}
48+
49+
function search(searcher, queryString) {
50+
var query = java.callStaticMethodSync("org.apache.lucene.queryParser.QueryParser", "parse", queryString);
51+
var topDocs = searcher.search(query, 10);
52+
53+
console.log(topDocs);
54+
console.log("Found " + topDocs.totalHits + " hits for query " + queryString + ".")
55+
for(var i=0; i<topDocs.totalHits; i++) {
56+
var docId = topDocs.scoreDocs[i].doc;
57+
var doc = searcher.doc(docId);
58+
console.log((i + 1) + ". " + doc.get("title"));
59+
}
60+
}
1.4 MB
Binary file not shown.

src/java.cpp

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethodSync", callStaticMethodSync);
2222
NODE_SET_PROTOTYPE_METHOD(s_ct, "newArray", newArray);
2323
NODE_SET_PROTOTYPE_METHOD(s_ct, "newByte", newByte);
24+
NODE_SET_PROTOTYPE_METHOD(s_ct, "getStaticFieldValue", getStaticFieldValue);
2425

2526
target->Set(v8::String::NewSymbol("Java"), s_ct->GetFunction());
2627
}
@@ -137,6 +138,17 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
137138
}
138139
std::list<jobject> constructors = javaReflectionGetConstructors(env, clazz);
139140
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgTypes);
141+
if(method == NULL) {
142+
std::ostringstream errStr;
143+
errStr << "Could not find constructor";
144+
v8::Handle<v8::Value> error = javaExceptionToV8(env, errStr.str());
145+
146+
v8::Handle<v8::Value> argv[2];
147+
argv[0] = error;
148+
argv[1] = v8::Undefined();
149+
v8::Function::Cast(*callback)->Call(v8::Context::GetCurrent()->Global(), 2, argv);
150+
return v8::Undefined();
151+
}
140152

141153
// run
142154
NewInstanceBaton* baton = new NewInstanceBaton(self, clazz, method, methodArgs, callback);
@@ -155,6 +167,7 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
155167
JNIEnv* env = self->getJavaEnv();
156168

157169
int argsEnd = args.Length();
170+
int argsStart = 0;
158171

159172
// argument - className
160173
if(args.Length() < 1 || !args[0]->IsString()) {
@@ -163,9 +176,10 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
163176
v8::Local<v8::String> classNameObj = v8::Local<v8::String>::Cast(args[0]);
164177
v8::String::AsciiValue classNameVal(classNameObj);
165178
std::string className = *classNameVal;
179+
argsStart++;
166180

167181
std::list<int> methodArgTypes;
168-
jarray methodArgs = v8ToJava(env, args, 1, argsEnd, &methodArgTypes);
182+
jarray methodArgs = v8ToJava(env, args, argsStart, argsEnd, &methodArgTypes);
169183

170184
jclass clazz = javaFindClass(env, className);
171185
if(clazz == NULL) {
@@ -175,6 +189,11 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
175189
}
176190
std::list<jobject> constructors = javaReflectionGetConstructors(env, clazz);
177191
jobject method = javaFindBestMatchingConstructor(env, constructors, methodArgTypes);
192+
if(method == NULL) {
193+
std::ostringstream errStr;
194+
errStr << "Could not find constructor";
195+
return ThrowException(javaExceptionToV8(env, errStr.str()));
196+
}
178197

179198
// run
180199
v8::Handle<v8::Value> callback = v8::Object::New();
@@ -412,3 +431,53 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
412431

413432
return scope.Close(JavaObject::New(self, newObj));
414433
}
434+
435+
/*static*/ v8::Handle<v8::Value> Java::getStaticFieldValue(const v8::Arguments& args) {
436+
v8::HandleScope scope;
437+
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
438+
v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm();
439+
if(!ensureJvmResults->IsUndefined()) {
440+
return ensureJvmResults;
441+
}
442+
JNIEnv* env = self->getJavaEnv();
443+
444+
// argument - className
445+
if(args.Length() < 1 || !args[0]->IsString()) {
446+
return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 0 must be a string")));
447+
}
448+
v8::Local<v8::String> classNameObj = v8::Local<v8::String>::Cast(args[0]);
449+
v8::String::AsciiValue classNameVal(classNameObj);
450+
std::string className = *classNameVal;
451+
452+
// argument - field name
453+
if(args.Length() < 2 || !args[1]->IsString()) {
454+
return ThrowException(v8::Exception::TypeError(v8::String::New("Argument 1 must be a string")));
455+
}
456+
v8::Local<v8::String> fieldNameObj = v8::Local<v8::String>::Cast(args[1]);
457+
v8::String::AsciiValue fieldNameVal(fieldNameObj);
458+
std::string fieldName = *fieldNameVal;
459+
460+
// find the class
461+
jclass clazz = javaFindClass(env, className);
462+
if(clazz == NULL) {
463+
std::ostringstream errStr;
464+
errStr << "Could not create class " << className.c_str();
465+
return ThrowException(javaExceptionToV8(env, errStr.str()));
466+
}
467+
468+
// get the field
469+
jobject field = javaFindField(env, clazz, fieldName);
470+
if(field == NULL) {
471+
std::ostringstream errStr;
472+
errStr << "Could not find field " << fieldName.c_str() << " on class " << className.c_str();
473+
return ThrowException(javaExceptionToV8(env, errStr.str()));
474+
}
475+
476+
// get field value
477+
jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
478+
jmethodID field_get = env->GetMethodID(fieldClazz, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
479+
jobject val = env->CallObjectMethod(field, field_get, NULL);
480+
481+
return scope.Close(JavaObject::New(self, val));
482+
}
483+

src/java.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Java : public node::ObjectWrap {
2525
static v8::Handle<v8::Value> callStaticMethodSync(const v8::Arguments& args);
2626
static v8::Handle<v8::Value> newArray(const v8::Arguments& args);
2727
static v8::Handle<v8::Value> newByte(const v8::Arguments& args);
28+
static v8::Handle<v8::Value> getStaticFieldValue(const v8::Arguments& args);
2829
v8::Handle<v8::Value> ensureJvm();
2930

3031
static v8::Persistent<v8::FunctionTemplate> s_ct;

src/methodCallBaton.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ void NewInstanceBaton::execute(JNIEnv *env) {
109109
jclass constructorClazz = env->FindClass("java/lang/reflect/Constructor");
110110
jmethodID constructor_newInstance = env->GetMethodID(constructorClazz, "newInstance", "([Ljava/lang/Object;)Ljava/lang/Object;");
111111

112+
//printf("invoke: %s\n", javaObjectToString(env, m_method).c_str());
113+
112114
jobject result = env->CallObjectMethod(m_method, constructor_newInstance, m_args);
113115
m_resultType = TYPE_OBJECT;
114116
m_result = env->NewGlobalRef(result);
@@ -124,6 +126,14 @@ void StaticMethodCallBaton::execute(JNIEnv *env) {
124126

125127
jclass returnType = (jclass)env->CallObjectMethod(m_method, method_getReturnType);
126128

129+
/*
130+
printf("calling %s\n", javaObjectToString(env, m_method).c_str());
131+
printf("arguments\n");
132+
for(int i=0; i<env->GetArrayLength(m_args); i++) {
133+
printf(" %s\n", javaObjectToString(env, env->GetObjectArrayElement((jobjectArray)m_args, i)).c_str());
134+
}
135+
*/
136+
127137
m_resultType = javaGetType(env, returnType);
128138
jobject result = env->CallObjectMethod(m_method, method_invoke, NULL, m_args);
129139
m_result = env->NewGlobalRef(result);

src/utils.cpp

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ jobject javaFindBestMatchingMethod(
7474
const char *methodName,
7575
std::list<int>& argTypes) {
7676

77+
std::list<jobject> possibleMatches;
7778
jclass methodClazz = env->FindClass("java/lang/reflect/Method");
7879
jmethodID method_getNameMethod = env->GetMethodID(methodClazz, "getName", "()Ljava/lang/String;");
7980
jmethodID method_getParameterTypes = env->GetMethodID(methodClazz, "getParameterTypes", "()[Ljava/lang/Class;");
@@ -83,10 +84,25 @@ jobject javaFindBestMatchingMethod(
8384
if(itMethodName == methodName) {
8485
jarray parameters = (jarray)env->CallObjectMethod(*it, method_getParameterTypes);
8586
if(env->GetArrayLength(parameters) == (jsize)argTypes.size()) {
86-
return *it; // TODO: check parameters
87+
possibleMatches.push_back(*it);
8788
}
8889
}
8990
}
91+
92+
if(possibleMatches.size() == 0) {
93+
return NULL;
94+
}
95+
if(possibleMatches.size() == 1) {
96+
return possibleMatches.front();
97+
} else {
98+
// TODO: argument match
99+
printf("javaFindBestMatchingMethod: multiple matches (choosing the first)\n");
100+
for(std::list<jobject>::iterator it = possibleMatches.begin(); it != possibleMatches.end(); it++) {
101+
printf(" %s\n", javaObjectToString(env, *it).c_str());
102+
}
103+
return possibleMatches.front();
104+
}
105+
90106
return NULL;
91107
}
92108

@@ -95,15 +111,31 @@ jobject javaFindBestMatchingConstructor(
95111
std::list<jobject>& constructors,
96112
std::list<int>& argTypes) {
97113

114+
std::list<jobject> possibleMatches;
98115
jclass constructorClazz = env->FindClass("java/lang/reflect/Constructor");
99116
jmethodID constructor_getParameterTypes = env->GetMethodID(constructorClazz, "getParameterTypes", "()[Ljava/lang/Class;");
100117

101118
for(std::list<jobject>::iterator it = constructors.begin(); it != constructors.end(); it++) {
102119
jarray parameters = (jarray)env->CallObjectMethod(*it, constructor_getParameterTypes);
103120
if(env->GetArrayLength(parameters) == (jsize)argTypes.size()) {
104-
return *it; // TODO: check parameters
121+
possibleMatches.push_back(*it);
122+
}
123+
}
124+
125+
if(possibleMatches.size() == 0) {
126+
return NULL;
127+
}
128+
if(possibleMatches.size() == 1) {
129+
return possibleMatches.front();
130+
} else {
131+
// TODO: argument match
132+
printf("javaFindBestMatchingConstructor: multiple matches (choosing the first)\n");
133+
for(std::list<jobject>::iterator it = possibleMatches.begin(); it != possibleMatches.end(); it++) {
134+
printf(" %s\n", javaObjectToString(env, *it).c_str());
105135
}
136+
return possibleMatches.front();
106137
}
138+
107139
return NULL;
108140
}
109141

@@ -148,18 +180,53 @@ jclass javaFindClass(JNIEnv* env, std::string className) {
148180
return clazz;
149181
}
150182

183+
jobject javaFindField(JNIEnv* env, jclass clazz, std::string fieldName) {
184+
jclass clazzclazz = env->GetObjectClass(clazz);
185+
jclass fieldClazz = env->FindClass("java/lang/reflect/Field");
186+
jmethodID field_getName = env->GetMethodID(fieldClazz, "getName", "()Ljava/lang/String;");
187+
jmethodID class_getFields = env->GetMethodID(clazzclazz, "getFields", "()[Ljava/lang/reflect/Field;");
188+
jobjectArray fieldObjects = (jobjectArray)env->CallObjectMethod(clazz, class_getFields);
189+
190+
jsize fieldCount = env->GetArrayLength(fieldObjects);
191+
for(jsize i=0; i<fieldCount; i++) {
192+
jobject field = env->GetObjectArrayElement(fieldObjects, i);
193+
std::string fieldName = javaToString(env, (jstring)env->CallObjectMethod(field, field_getName));
194+
if(strcmp(fieldName.c_str(), fieldName.c_str()) == 0) {
195+
return field;
196+
}
197+
}
198+
199+
return NULL;
200+
}
201+
151202
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg, int *methodArgType) {
203+
if(arg->IsNull()) {
204+
return NULL;
205+
}
206+
152207
if(arg->IsString()) {
153208
*methodArgType = TYPE_STRING;
154209
v8::String::AsciiValue val(arg->ToString());
155210
return env->NewStringUTF(*val);
156-
} else if(arg->IsInt32()) {
211+
}
212+
213+
if(arg->IsInt32()) {
157214
jint val = arg->ToInt32()->Value();
158215
*methodArgType = TYPE_INT;
159216
jclass clazz = env->FindClass("java/lang/Integer");
160217
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(I)V");
161218
return env->NewObject(clazz, constructor, val);
162-
} else if(arg->IsObject()) {
219+
}
220+
221+
if(arg->IsBoolean()) {
222+
jboolean val = arg->ToBoolean()->Value();
223+
*methodArgType = TYPE_BOOLEAN;
224+
jclass clazz = env->FindClass("java/lang/Boolean");
225+
jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V");
226+
return env->NewObject(clazz, constructor, val);
227+
}
228+
229+
if(arg->IsObject()) {
163230
v8::Local<v8::Object> obj = v8::Object::Cast(*arg);
164231
v8::String::AsciiValue constructorName(obj->GetConstructorName());
165232
if(strcmp(*constructorName, "JavaObject") == 0) {

src/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ JNIEnv* javaAttachCurrentThread(JavaVM* jvm);
3535
void javaDetachCurrentThread(JavaVM* jvm);
3636
jvalueType javaGetType(JNIEnv *env, jclass type);
3737
jclass javaFindClass(JNIEnv* env, std::string className);
38+
jobject javaFindField(JNIEnv* env, jclass clazz, std::string fieldName);
3839
jarray v8ToJava(JNIEnv* env, const v8::Arguments& args, int start, int end, std::list<int> *methodArgTypes);
3940
jobject v8ToJava(JNIEnv* env, v8::Local<v8::Value> arg, int *methodArgType);
4041
v8::Handle<v8::Value> javaExceptionToV8(JNIEnv* env, const std::string& alternateMessage);

0 commit comments

Comments
 (0)