Permalink
Browse files

added a require method (see issue #2)

  • Loading branch information...
1 parent 87c2083 commit 1e3d2f1a66f946fbf539fb400f8828e85faeb7a0 @joeferner committed Feb 24, 2012
View
@@ -5,3 +5,4 @@ node_modules
*.swp
.lock*
npm-debug.log
+.idea
View
@@ -40,11 +40,16 @@ java.newInstance("java.util.ArrayList", function(err, list) {
list.addSync("item1");
list.addSync("item2");
});
+
+var ArrayList = java.require('java.util.ArrayList');
+var list = new ArrayList();
+list.addSync('item1');
```
# Index
## java
+ * [require](#javaRequire)
* [newInstance](#javaNewInstance)
* [callStaticMethod](#javaCallStaticMethod)
* [getStaticFieldValue](#javaGetStaticFieldValue)
@@ -61,6 +66,24 @@ java.newInstance("java.util.ArrayList", function(err, list) {
<a name="java"/>
## java
+<a name="javaRequire" />
+**java.require(className)**
+
+Loads the class given by className such that it acts and feels like a javascript object.
+
+__Arguments__
+
+ * className - The name of the class to create. For subclasses seperate using a '$' (eg. com.nearinfinty.MyClass$SubClass)
+
+__Example__
+
+ var Test = java.require('Test');
+ Test.someStaticMethodSync(5);
+ console.log(Test.someStaticField);
+
+ var test = new Test();
+ list.instanceMethodSync('item1');
+
<a name="javaNewInstance" />
**java.newInstance(className, [args...], callback)**
View
@@ -1,5 +1,49 @@
+'use strict';
var bindings = require("../build/Release/nodejavabridge_bindings");
var java = module.exports = new bindings.Java();
java.classpath.push(__dirname + "/../commons-lang3-node-java.jar");
+
+var MODIFIER_PUBLIC = 1;
+var MODIFIER_STATIC = 8;
+
+java.require = function (name) {
+ var clazz = java.findClassSync(name); // TODO: change to Class.forName when classloader issue is resolved.
+ var result = function () {
+ var args = [name];
+ for (var i = 0; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ return java.newInstanceSync.apply(java, args);
+ };
+ var i;
+
+ // copy static fields
+ var fields = clazz.getDeclaredFieldsSync();
+ for (i = 0; i < fields.length; i++) {
+ if (((fields[i].getModifiersSync() & MODIFIER_PUBLIC) === MODIFIER_PUBLIC)
+ && ((fields[i].getModifiersSync() & MODIFIER_STATIC) === MODIFIER_STATIC)) {
+ var fieldName = fields[i].getNameSync();
+ result.__defineGetter__(fieldName, function (name, fieldName) {
+ return java.getStaticFieldValue(name, fieldName);
+ }.bind(this, name, fieldName));
+ result.__defineSetter__(fieldName, function (name, fieldName, val) {
+ java.setStaticFieldValue(name, fieldName, val);
+ }.bind(this, name, fieldName));
+ }
+ }
+
+ // copy static methods
+ var methods = clazz.getDeclaredMethodsSync();
+ for (i = 0; i < methods.length; i++) {
+ if (((methods[i].getModifiersSync() & MODIFIER_PUBLIC) === MODIFIER_PUBLIC)
+ && ((methods[i].getModifiersSync() & MODIFIER_STATIC) === MODIFIER_STATIC)) {
+ var methodName = methods[i].getNameSync();
+ result[methodName + 'Sync'] = java.callStaticMethodSync.bind(java, name, methodName);
+ result[methodName] = java.callStaticMethod.bind(java, name, methodName);
+ }
+ }
+
+ return result;
+};
View
@@ -14,7 +14,7 @@
"licenses": [ { "type" : "MIT" } ],
"repositories": { "type": "git", "url": "https://github.com/nearinfinity/node-java.git" },
"dependencies": {
- "mnm": "~0.0.2"
+ "mnm": "~0.0.3"
},
"devDependencies": {
"nodeunit": "~0.6.4"
View
@@ -19,6 +19,7 @@
NODE_SET_PROTOTYPE_METHOD(s_ct, "newInstanceSync", newInstanceSync);
NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethod", callStaticMethod);
NODE_SET_PROTOTYPE_METHOD(s_ct, "callStaticMethodSync", callStaticMethodSync);
+ NODE_SET_PROTOTYPE_METHOD(s_ct, "findClassSync", findClassSync);
NODE_SET_PROTOTYPE_METHOD(s_ct, "newArray", newArray);
NODE_SET_PROTOTYPE_METHOD(s_ct, "newByte", newByte);
NODE_SET_PROTOTYPE_METHOD(s_ct, "getStaticFieldValue", getStaticFieldValue);
@@ -282,6 +283,34 @@ v8::Handle<v8::Value> Java::createJVM(JavaVM** jvm, JNIEnv** env) {
return scope.Close(result);
}
+/*static*/ v8::Handle<v8::Value> Java::findClassSync(const v8::Arguments& args) {
+ v8::HandleScope scope;
+ Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
+ v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm();
+ if(!ensureJvmResults->IsUndefined()) {
+ return ensureJvmResults;
+ }
+ JNIEnv* env = self->getJavaEnv();
+
+ int argsStart = 0;
+ int argsEnd = args.Length();
+
+ // arguments
+ ARGS_FRONT_CLASSNAME();
+
+ // find class
+ jclass clazz = javaFindClass(env, className);
+ if(clazz == NULL) {
+ std::ostringstream errStr;
+ errStr << "Could not create class " << className.c_str();
+ return ThrowException(javaExceptionToV8(env, errStr.str()));
+ }
+
+ // run
+ v8::Handle<v8::Value> result = javaToV8(self, env, clazz);
+ return scope.Close(result);
+}
+
/*static*/ v8::Handle<v8::Value> Java::newArray(const v8::Arguments& args) {
v8::HandleScope scope;
Java* self = node::ObjectWrap::Unwrap<Java>(args.This());
View
@@ -23,6 +23,7 @@ class Java : public node::ObjectWrap {
static v8::Handle<v8::Value> newInstanceSync(const v8::Arguments& args);
static v8::Handle<v8::Value> callStaticMethod(const v8::Arguments& args);
static v8::Handle<v8::Value> callStaticMethodSync(const v8::Arguments& args);
+ static v8::Handle<v8::Value> findClassSync(const v8::Arguments& args);
static v8::Handle<v8::Value> newArray(const v8::Arguments& args);
static v8::Handle<v8::Value> newByte(const v8::Arguments& args);
static v8::Handle<v8::Value> getStaticFieldValue(const v8::Arguments& args);
View
@@ -117,6 +117,20 @@ jvalueType javaGetType(JNIEnv *env, jclass type) {
jclass javaFindClass(JNIEnv* env, std::string& className) {
std::string searchClassName = className;
std::replace(searchClassName.begin(), searchClassName.end(), '.', '/');
+
+// Alternate find class trying to fix Class.forName
+// jclass threadClazz = env->FindClass("java/lang/Thread");
+// jmethodID thread_getCurrentThread = env->GetStaticMethodID(threadClazz, "currentThread", "()Ljava/lang/Thread;");
+// jmethodID thread_getContextClassLoader = env->GetMethodID(threadClazz, "getContextClassLoader", "()Ljava/lang/ClassLoader;");
+//
+// jclass classLoaderClazz = env->FindClass("java/lang/ClassLoader");
+// jmethodID classLoader_loadClass = env->GetMethodID(classLoaderClazz, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+//
+// jobject currentThread = env->CallObjectMethod(threadClazz, thread_getCurrentThread);
+// jobject classLoader = env->CallObjectMethod(currentThread, thread_getContextClassLoader);
+// jstring searchClassNameJava = env->NewStringUTF(className.c_str());
+// jclass clazz = (jclass)env->CallObjectMethod(classLoader, classLoader_loadClass, searchClassNameJava);
+
jclass clazz = env->FindClass(searchClassName.c_str());
return clazz;
}
@@ -340,8 +354,13 @@ jobjectArray javaObjectArrayToClasses(JNIEnv *env, jobjectArray objs) {
jsize objsLength = env->GetArrayLength(objs);
jobjectArray results = env->NewObjectArray(objsLength, clazzClazz, NULL);
for(jsize i=0; i<objsLength; i++) {
- jclass objClazz = env->GetObjectClass(env->GetObjectArrayElement(objs, i));
- env->SetObjectArrayElement(results, i, objClazz);
+ jobject elem = env->GetObjectArrayElement(objs, i);
+ if(elem == NULL) {
+ env->SetObjectArrayElement(results, i, NULL);
+ } else {
+ jclass objClazz = env->GetObjectClass(elem);
+ env->SetObjectArrayElement(results, i, objClazz);
+ }
}
return results;
}
View
@@ -1,5 +1,5 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
@@ -1,5 +1,5 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
@@ -1,5 +1,5 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
@@ -1,10 +1,15 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
exports['Java - Static Field'] = nodeunit.testCase({
+ tearDown: function (callback) {
+ java.setStaticFieldValue("Test", "staticFieldInt", 42);
+ callback();
+ },
+
"getStaticFieldValue int": function(test) {
var val = java.getStaticFieldValue("Test", "staticFieldInt");
test.equal(val, 42);
View
@@ -1,5 +1,5 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
View
@@ -0,0 +1,29 @@
+'use strict';
+
+var java = require("../testHelpers").java;
+var nodeunit = require("nodeunit");
+var util = require("util");
+
+exports['Require Class'] = nodeunit.testCase({
+ tearDown: function (callback) {
+ java.setStaticFieldValue("Test", "staticFieldInt", 42);
+ callback();
+ },
+
+ "require": function (test) {
+ var Test = java.require('Test');
+ test.equals(42, Test.staticFieldInt);
+ Test.staticFieldInt = 200;
+ test.equals(200, Test.staticFieldInt);
+
+ test.equals(100, Test.staticMethodSync(99));
+ Test.staticMethod(99, function (err, result) {
+ test.ok(!err);
+ test.equals(100, result);
+
+ var testObj = new Test(5);
+ test.equals(5, testObj.getIntSync());
+ test.done();
+ });
+ }
+});
View
@@ -1,4 +1,4 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
View
@@ -1,5 +1,5 @@
-var java = require("./testHelpers").java;
+var java = require("../testHelpers").java;
var nodeunit = require("nodeunit");
var util = require("util");
@@ -1,7 +1,7 @@
-var java = require("../");
+var java = require("./");
java.options.push("-Djava.awt.headless=true");
java.classpath.push("test/");
java.classpath.push("test/commons-lang3-3.1.jar");
-module.exports.java = java;
+module.exports.java = java;

0 comments on commit 1e3d2f1

Please sign in to comment.