33#include < string.h>
44#include " javaObject.h"
55#include " methodCallBaton.h"
6+ #include < sstream>
67
78/* static*/ v8::Persistent<v8::FunctionTemplate> Java::s_ct;
89
1617
1718 NODE_SET_PROTOTYPE_METHOD (s_ct, " newInstance" , newInstance);
1819 NODE_SET_PROTOTYPE_METHOD (s_ct, " newInstanceSync" , newInstanceSync);
20+ NODE_SET_PROTOTYPE_METHOD (s_ct, " callStaticMethod" , callStaticMethod);
21+ NODE_SET_PROTOTYPE_METHOD (s_ct, " callStaticMethodSync" , callStaticMethodSync);
1922
2023 target->Set (v8::String::NewSymbol (" Java" ), s_ct->GetFunction ());
2124}
2528
2629 Java *self = new Java ();
2730 self->Wrap (args.This ());
31+
32+ self->handle_ ->Set (v8::String::New (" classpath" ), v8::Array::New ());
33+
2834 return args.This ();
2935}
3036
3137Java::Java () {
3238 this ->m_jvm = NULL ;
3339 this ->m_env = NULL ;
34- createJVM (&this ->m_jvm , &this ->m_env );
3540}
3641
3742Java::~Java () {
3843
3944}
4045
41- /* static*/ void Java::createJVM (JavaVM** jvm, JNIEnv** env) {
46+ v8::Handle<v8::Value> Java::ensureJvm () {
47+ if (!m_jvm) {
48+ return createJVM (&this ->m_jvm , &this ->m_env );
49+ }
50+
51+ return v8::Undefined ();
52+ }
53+
54+ v8::Handle<v8::Value> Java::createJVM (JavaVM** jvm, JNIEnv** env) {
4255 JavaVM* jvmTemp;
4356 JavaVMInitArgs args;
4457
45- args.version = JNI_VERSION_1_4 ;
58+ std::ostringstream classPath;
59+ classPath << " -Djava.class.path=" ;
60+
61+ v8::Local<v8::Value> classPathValue = handle_->Get (v8::String::New (" classpath" ));
62+ if (!classPathValue->IsArray ()) {
63+ return ThrowException (v8::Exception::TypeError (v8::String::New (" Classpath must be an array" )));
64+ }
65+ v8::Local<v8::Array> classPathArray = v8::Array::Cast (*classPathValue);
66+ for (uint32_t i=0 ; i<classPathArray->Length (); i++) {
67+ if (i != 0 ) {
68+ classPath << " :" ; // TODO: figure out path seperator
69+ }
70+ v8::Local<v8::Value> arrayItemValue = classPathArray->Get (i);
71+ if (!arrayItemValue->IsString ()) {
72+ return ThrowException (v8::Exception::TypeError (v8::String::New (" Classpath must only contain strings" )));
73+ }
74+ v8::Local<v8::String> arrayItem = arrayItemValue->ToString ();
75+ v8::String::AsciiValue arrayItemStr (arrayItem);
76+ classPath << *arrayItemStr;
77+ }
78+
79+ JavaVMOption options[1 ];
80+ options[0 ].optionString = strdup (classPath.str ().c_str ());
81+
4682 JNI_GetDefaultJavaVMInitArgs (&args);
83+ args.version = JNI_VERSION_1_6 ;
84+ args.ignoreUnrecognized = false ;
85+ args.options = options;
86+ args.nOptions = 1 ;
4787 JNI_CreateJavaVM (&jvmTemp, (void **)env, &args);
4888 *jvm = jvmTemp;
89+
90+ return v8::Undefined ();
4991}
5092
5193/* static*/ v8::Handle<v8::Value> Java::newInstance (const v8::Arguments& args) {
5294 v8::HandleScope scope;
5395 Java* self = node::ObjectWrap::Unwrap<Java>(args.This ());
96+ v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm ();
97+ if (!ensureJvmResults->IsUndefined ()) {
98+ return ensureJvmResults;
99+ }
54100 JNIEnv* env = self->getJavaEnv ();
55101
56- int argsEnd = args.Length ();
57-
102+ int argsEnd = args.Length ();
103+
58104 // argument - className
59105 if (args.Length () < 1 || !args[0 ]->IsString ()) {
60106 return ThrowException (v8::Exception::TypeError (v8::String::New (" Argument 0 must be a string" )));
@@ -73,12 +119,17 @@ Java::~Java() {
73119 }
74120
75121 std::list<int > methodArgTypes;
76- jarray methodArgs = v8ToJava (env, args, 1 , argsEnd, &methodArgTypes);
77-
122+ jarray methodArgs = v8ToJava (env, args, 1 , argsEnd, &methodArgTypes);
123+
78124 jclass clazz = javaFindClass (env, className);
79- std::list<jobject> constructors = javaReflectionGetConstructors (env, clazz);
125+ if (clazz == NULL ) {
126+ std::ostringstream errStr;
127+ errStr << " Could not create class " << className.c_str ();
128+ return javaExceptionToV8 (env, errStr.str ());
129+ }
130+ std::list<jobject> constructors = javaReflectionGetConstructors (env, clazz);
80131 jobject method = javaFindBestMatchingConstructor (env, constructors, methodArgTypes);
81-
132+
82133 // run
83134 NewInstanceBaton* baton = new NewInstanceBaton (self, clazz, method, methodArgs, callback);
84135 baton->run ();
@@ -89,10 +140,14 @@ Java::~Java() {
89140/* static*/ v8::Handle<v8::Value> Java::newInstanceSync (const v8::Arguments& args) {
90141 v8::HandleScope scope;
91142 Java* self = node::ObjectWrap::Unwrap<Java>(args.This ());
143+ v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm ();
144+ if (!ensureJvmResults->IsUndefined ()) {
145+ return ensureJvmResults;
146+ }
92147 JNIEnv* env = self->getJavaEnv ();
93148
94- int argsEnd = args.Length ();
95-
149+ int argsEnd = args.Length ();
150+
96151 // argument - className
97152 if (args.Length () < 1 || !args[0 ]->IsString ()) {
98153 return ThrowException (v8::Exception::TypeError (v8::String::New (" Argument 0 must be a string" )));
@@ -105,13 +160,72 @@ Java::~Java() {
105160 jarray methodArgs = v8ToJava (env, args, 1 , argsEnd, &methodArgTypes);
106161
107162 jclass clazz = javaFindClass (env, className);
108- std::list<jobject> constructors = javaReflectionGetConstructors (env, clazz);
163+ if (clazz == NULL ) {
164+ std::ostringstream errStr;
165+ errStr << " Could not create class " << className.c_str ();
166+ return javaExceptionToV8 (env, errStr.str ());
167+ }
168+ std::list<jobject> constructors = javaReflectionGetConstructors (env, clazz);
109169 jobject method = javaFindBestMatchingConstructor (env, constructors, methodArgTypes);
110-
170+
111171 // run
112172 v8::Handle<v8::Value> callback = v8::Object::New ();
113173 NewInstanceBaton* baton = new NewInstanceBaton (self, clazz, method, methodArgs, callback);
114174 v8::Handle<v8::Value> result = baton->runSync ();
115175 delete baton;
116176 return scope.Close (result);
117177}
178+
179+ /* static*/ v8::Handle<v8::Value> Java::callStaticMethod (const v8::Arguments& args) {
180+ // TODO: write me
181+ return v8::Undefined ();
182+ }
183+
184+ /* static*/ v8::Handle<v8::Value> Java::callStaticMethodSync (const v8::Arguments& args) {
185+ v8::HandleScope scope;
186+ Java* self = node::ObjectWrap::Unwrap<Java>(args.This ());
187+ v8::Handle<v8::Value> ensureJvmResults = self->ensureJvm ();
188+ if (!ensureJvmResults->IsUndefined ()) {
189+ return ensureJvmResults;
190+ }
191+ JNIEnv* env = self->getJavaEnv ();
192+
193+ int argsEnd = args.Length ();
194+
195+ // argument - className
196+ if (args.Length () < 1 || !args[0 ]->IsString ()) {
197+ return ThrowException (v8::Exception::TypeError (v8::String::New (" Argument 0 must be a string" )));
198+ }
199+ v8::Local<v8::String> classNameObj = v8::Local<v8::String>::Cast (args[0 ]);
200+ v8::String::AsciiValue classNameVal (classNameObj);
201+ std::string className = *classNameVal;
202+
203+ // argument - method name
204+ if (args.Length () < 2 || !args[1 ]->IsString ()) {
205+ return ThrowException (v8::Exception::TypeError (v8::String::New (" Argument 1 must be a string" )));
206+ }
207+ v8::Local<v8::String> methodNameObj = v8::Local<v8::String>::Cast (args[1 ]);
208+ v8::String::AsciiValue methodNameVal (methodNameObj);
209+ std::string methodName = *methodNameVal;
210+
211+ // build args
212+ std::list<int > methodArgTypes;
213+ jarray methodArgs = v8ToJava (env, args, 2 , argsEnd, &methodArgTypes);
214+
215+ // find class and method
216+ jclass clazz = javaFindClass (env, className);
217+ if (clazz == NULL ) {
218+ std::ostringstream errStr;
219+ errStr << " Could not create class " << className.c_str ();
220+ return javaExceptionToV8 (env, errStr.str ());
221+ }
222+ std::list<jobject> staticMethods = javaReflectionGetStaticMethods (env, clazz);
223+ jobject method = javaFindBestMatchingMethod (env, staticMethods, methodName.c_str (), methodArgTypes);
224+
225+ // run
226+ v8::Handle<v8::Value> callback = v8::Object::New ();
227+ StaticMethodCallBaton* baton = new StaticMethodCallBaton (self, clazz, method, methodArgs, callback);
228+ v8::Handle<v8::Value> result = baton->runSync ();
229+ delete baton;
230+ return scope.Close (result);
231+ }
0 commit comments