Skip to content

Commit 1e3d2f1

Browse files
committed
added a require method (see issue #2)
1 parent 87c2083 commit 1e3d2f1

16 files changed

+163
-12
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ node_modules
55
*.swp
66
.lock*
77
npm-debug.log
8+
.idea

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,16 @@ java.newInstance("java.util.ArrayList", function(err, list) {
4040
list.addSync("item1");
4141
list.addSync("item2");
4242
});
43+
44+
var ArrayList = java.require('java.util.ArrayList');
45+
var list = new ArrayList();
46+
list.addSync('item1');
4347
```
4448

4549
# Index
4650

4751
## java
52+
* [require](#javaRequire)
4853
* [newInstance](#javaNewInstance)
4954
* [callStaticMethod](#javaCallStaticMethod)
5055
* [getStaticFieldValue](#javaGetStaticFieldValue)
@@ -61,6 +66,24 @@ java.newInstance("java.util.ArrayList", function(err, list) {
6166
<a name="java"/>
6267
## java
6368

69+
<a name="javaRequire" />
70+
**java.require(className)**
71+
72+
Loads the class given by className such that it acts and feels like a javascript object.
73+
74+
__Arguments__
75+
76+
* className - The name of the class to create. For subclasses seperate using a '$' (eg. com.nearinfinty.MyClass$SubClass)
77+
78+
__Example__
79+
80+
var Test = java.require('Test');
81+
Test.someStaticMethodSync(5);
82+
console.log(Test.someStaticField);
83+
84+
var test = new Test();
85+
list.instanceMethodSync('item1');
86+
6487
<a name="javaNewInstance" />
6588
**java.newInstance(className, [args...], callback)**
6689

lib/nodeJavaBridge.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
1+
'use strict';
12

23
var bindings = require("../build/Release/nodejavabridge_bindings");
34

45
var java = module.exports = new bindings.Java();
56
java.classpath.push(__dirname + "/../commons-lang3-node-java.jar");
7+
8+
var MODIFIER_PUBLIC = 1;
9+
var MODIFIER_STATIC = 8;
10+
11+
java.require = function (name) {
12+
var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved.
13+
var result = function () {
14+
var args = [name];
15+
for (var i = 0; i < arguments.length; i++) {
16+
args.push(arguments[i]);
17+
}
18+
return java.newInstanceSync.apply(java, args);
19+
};
20+
var i;
21+
22+
// copy static fields
23+
var fields = clazz.getDeclaredFieldsSync();
24+
for (i = 0; i < fields.length; i++) {
25+
if (((fields[i].getModifiersSync() & MODIFIER_PUBLIC) === MODIFIER_PUBLIC)
26+
&& ((fields[i].getModifiersSync() & MODIFIER_STATIC) === MODIFIER_STATIC)) {
27+
var fieldName = fields[i].getNameSync();
28+
result.__defineGetter__(fieldName, function (name, fieldName) {
29+
return java.getStaticFieldValue(name, fieldName);
30+
}.bind(this, name, fieldName));
31+
result.__defineSetter__(fieldName, function (name, fieldName, val) {
32+
java.setStaticFieldValue(name, fieldName, val);
33+
}.bind(this, name, fieldName));
34+
}
35+
}
36+
37+
// copy static methods
38+
var methods = clazz.getDeclaredMethodsSync();
39+
for (i = 0; i < methods.length; i++) {
40+
if (((methods[i].getModifiersSync() & MODIFIER_PUBLIC) === MODIFIER_PUBLIC)
41+
&& ((methods[i].getModifiersSync() & MODIFIER_STATIC) === MODIFIER_STATIC)) {
42+
var methodName = methods[i].getNameSync();
43+
result[methodName + 'Sync'] = java.callStaticMethodSync.bind(java, name, methodName);
44+
result[methodName] = java.callStaticMethod.bind(java, name, methodName);
45+
}
46+
}
47+
48+
return result;
49+
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"licenses": [ { "type" : "MIT" } ],
1515
"repositories": { "type": "git", "url": "https://github.com/nearinfinity/node-java.git" },
1616
"dependencies": {
17-
"mnm": "~0.0.2"
17+
"mnm": "~0.0.3"
1818
},
1919
"devDependencies": {
2020
"nodeunit": "~0.6.4"

src/java.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstanceSync", newInstanceSync);
2020
NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethod", callStaticMethod);
2121
NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethodSync", callStaticMethodSync);
22+
NODE_SET_PROTOTYPE_METHOD(s_ct, "findClassSync", findClassSync);
2223
NODE_SET_PROTOTYPE_METHOD(s_ct, "newArray", newArray);
2324
NODE_SET_PROTOTYPE_METHOD(s_ct, "newByte", newByte);
2425
NODE_SET_PROTOTYPE_METHOD(s_ct, "getStaticFieldValue", getStaticFieldValue);
@@ -282,6 +283,34 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
282283
return scope.Close(result);
283284
}
284285

286+
/*static*/ v8::Handle<v8::Value> Java::findClassSync(const v8::Arguments& args) {
287+
v8::HandleScope scope;
288+
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
289+
v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm();
290+
if(!ensureJvmResults->IsUndefined()) {
291+
return ensureJvmResults;
292+
}
293+
JNIEnv* env = self->getJavaEnv();
294+
295+
int argsStart = 0;
296+
int argsEnd = args.Length();
297+
298+
// arguments
299+
ARGS_FRONT_CLASSNAME();
300+
301+
// find class
302+
jclass clazz = javaFindClass(env, className);
303+
if(clazz == NULL) {
304+
std::ostringstream errStr;
305+
errStr << "Could not create class " << className.c_str();
306+
return ThrowException(javaExceptionToV8(env, errStr.str()));
307+
}
308+
309+
// run
310+
v8::Handle<v8::Value> result = javaToV8(self, env, clazz);
311+
return scope.Close(result);
312+
}
313+
285314
/*static*/ v8::Handle<v8::Value> Java::newArray(const v8::Arguments& args) {
286315
v8::HandleScope scope;
287316
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());

src/java.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Java : public node::ObjectWrap {
2323
static v8::Handle<v8::Value> newInstanceSync(const v8::Arguments& args);
2424
static v8::Handle<v8::Value> callStaticMethod(const v8::Arguments& args);
2525
static v8::Handle<v8::Value> callStaticMethodSync(const v8::Arguments& args);
26+
static v8::Handle<v8::Value> findClassSync(const v8::Arguments& args);
2627
static v8::Handle<v8::Value> newArray(const v8::Arguments& args);
2728
static v8::Handle<v8::Value> newByte(const v8::Arguments& args);
2829
static v8::Handle<v8::Value> getStaticFieldValue(const v8::Arguments& args);

src/utils.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ jvalueType javaGetType(JNIEnv *env, jclass type) {
117117
jclass javaFindClass(JNIEnv* env, std::string& className) {
118118
std::string searchClassName = className;
119119
std::replace(searchClassName.begin(), searchClassName.end(), '.', '/');
120+
121+
// Alternate find class trying to fix Class.forName
122+
// jclass threadClazz = env->FindClass("java/lang/Thread");
123+
// jmethodID thread_getCurrentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;");
124+
// jmethodID thread_getContextClassLoader = env->GetMethodID(threadClazz, "getContextClassLoader", "()Ljava/lang/ClassLoader;");
125+
//
126+
// jclass classLoaderClazz = env->FindClass("java/lang/ClassLoader");
127+
// jmethodID classLoader_loadClass = env->GetMethodID(classLoaderClazz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
128+
//
129+
// jobject currentThread = env->CallObjectMethod(threadClazz, thread_getCurrentThread);
130+
// jobject classLoader = env->CallObjectMethod(currentThread, thread_getContextClassLoader);
131+
// jstring searchClassNameJava = env->NewStringUTF(className.c_str());
132+
// jclass clazz = (jclass)env->CallObjectMethod(classLoader, classLoader_loadClass, searchClassNameJava);
133+
120134
jclass clazz = env->FindClass(searchClassName.c_str());
121135
return clazz;
122136
}
@@ -340,8 +354,13 @@ jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs) {
340354
jsize objsLength = env->GetArrayLength(objs);
341355
jobjectArray results = env->NewObjectArray(objsLength, clazzClazz, NULL);
342356
for(jsize i=0; i<objsLength; i++) {
343-
jclass objClazz = env->GetObjectClass(env->GetObjectArrayElement(objs, i));
344-
env->SetObjectArrayElement(results, i, objClazz);
357+
jobject elem = env->GetObjectArrayElement(objs, i);
358+
if(elem == NULL) {
359+
env->SetObjectArrayElement(results, i, NULL);
360+
} else {
361+
jclass objClazz = env->GetObjectClass(elem);
362+
env->SetObjectArrayElement(results, i, objClazz);
363+
}
345364
}
346365
return results;
347366
}

test/awt-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
var java = require("./testHelpers").java;
2+
var java = require("../testHelpers").java;
33

44
var nodeunit = require("nodeunit");
55
var util = require("util");

test/java-callStaticMethod-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
var java = require("./testHelpers").java;
2+
var java = require("../testHelpers").java;
33

44
var nodeunit = require("nodeunit");
55
var util = require("util");

test/java-newInstance-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
var java = require("./testHelpers").java;
2+
var java = require("../testHelpers").java;
33

44
var nodeunit = require("nodeunit");
55
var util = require("util");

0 commit comments

Comments
 (0)