/* * Free up a JavaFieldSpec and all its resources. */ void jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field) { JS_FREE_IF(cx, (char*)field->name); jsj_ReleaseJavaClassDescriptor(cx, jEnv, field->signature); JS_free(cx, field); }
static void destroy_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor) { JS_FREE_IF(cx, (char *)class_descriptor->name); if (class_descriptor->java_class) (*jEnv)->DeleteGlobalRef(jEnv, class_descriptor->java_class); if (class_descriptor->array_component_signature) jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor->array_component_signature); destroy_class_member_descriptors(cx, jEnv, class_descriptor->instance_members); destroy_class_member_descriptors(cx, jEnv, class_descriptor->static_members); destroy_class_member_descriptors(cx, jEnv, class_descriptor->constructors); JS_free(cx, class_descriptor); }
JavaClass_finalize(JSContext *cx, JSObject *obj) { JNIEnv *jEnv; JSJavaThreadState *jsj_env; JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj); if (!class_descriptor) return; /* Get the Java per-thread environment pointer for this JSContext */ jsj_env = jsj_EnterJava(cx, &jEnv); if (!jEnv) return; /* printf("Finalizing %s\n", class_descriptor->name); */ jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); jsj_ExitJava(jsj_env); }
/* * Reflect a Java object into a JS value. The source object, java_obj, must * be of type java.lang.Object or a subclass and may, therefore, be an array. */ JSBool jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv, jobject java_obj, jsval *vp) { JavaClassDescriptor *class_descriptor; jclass java_class; JSBool ret; /* A null in Java-land is also null in JS */ if (!java_obj) { *vp = JSVAL_NULL; return JS_TRUE; } java_class = (*jEnv)->GetObjectClass(jEnv, java_obj); class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); if (!class_descriptor) return JS_FALSE; switch (class_descriptor->type) { case JAVA_SIGNATURE_JAVA_LANG_BOOLEAN: ret = jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, vp); break; case JAVA_SIGNATURE_JAVA_LANG_DOUBLE: ret = jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, vp); break; case JAVA_SIGNATURE_JAVA_LANG_STRING: ret = jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp); break; default: ret = convert_javaobject_to_jsobject(cx, jEnv, class_descriptor, java_obj, vp); break; } (*jEnv)->DeleteLocalRef(jEnv, java_class); jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); return ret; }
/* * This is a wrapper around JS_ReportError(), useful when an error condition * is the result of a JVM failure or exception condition. It appends the * message associated with the pending Java exception to the passed in * printf-style format string and arguments. */ static void vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap) { jobject java_obj; jclass java_class; JavaClassDescriptor *class_descriptor; jthrowable java_exception; JSType wrapped_exception_type; jsval js_exception; java_obj = NULL; class_descriptor = NULL; /* Get the exception out of the java environment. */ java_exception = (*jEnv)->ExceptionOccurred(jEnv); if (!java_exception) { JSString *err_jsstr; char *err = JS_vsmprintf(format, ap); if (!err) return; err_jsstr = JS_NewString(cx, err, strlen(err)); if (!err_jsstr) return; JS_SetPendingException(cx, STRING_TO_JSVAL(err_jsstr)); return; } (*jEnv)->ExceptionClear(jEnv); /* Check for JSException */ if (njJSException && (*jEnv)->IsInstanceOf(jEnv, java_exception, njJSException)) { wrapped_exception_type = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_wrappedExceptionType); /* (int) to suppress warning */ if ((int)wrapped_exception_type != JSTYPE_EMPTY) { java_obj = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_wrappedException); if ((java_obj == NULL) && (wrapped_exception_type == JSTYPE_OBJECT)) { js_exception = JSVAL_NULL; } else { java_class = (*jEnv)->GetObjectClass(jEnv, java_obj); class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); /* OK to delete ref, since above call adds global ref */ (*jEnv)->DeleteLocalRef(jEnv, java_class); /* Convert native JS values back to native types. */ switch(wrapped_exception_type) { case JSTYPE_NUMBER: if (!jsj_ConvertJavaObjectToJSNumber(cx, jEnv, class_descriptor, java_obj, &js_exception)) goto error; break; case JSTYPE_BOOLEAN: if (!jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, class_descriptor, java_obj, &js_exception)) goto error; break; case JSTYPE_STRING: if (!jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, &js_exception)) goto error; break; case JSTYPE_VOID: js_exception = JSVAL_VOID; break; case JSTYPE_OBJECT: case JSTYPE_FUNCTION: default: if ((*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) { js_exception = OBJECT_TO_JSVAL(jsj_UnwrapJSObjectWrapper(jEnv, java_obj)); if (!js_exception) goto error; } else { if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_exception)) goto error; } } } } /* Check for internal exception */ } else { if (!JSJ_ConvertJavaObjectToJSValue(cx, java_exception, &js_exception)) { goto error; } } /* Set pending JS exception and clear the java exception. */ JS_SetPendingException(cx, js_exception); goto done; error: JS_ASSERT(0); jsj_LogError("Out of memory while attempting to throw JSException\n"); done: if (class_descriptor) jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); if (java_obj) (*jEnv)->DeleteLocalRef(jEnv, java_obj); if (java_exception) (*jEnv)->DeleteLocalRef(jEnv, java_exception); }
/* * Add a single field, described by java_field, to the JavaMemberDescriptor * named by field_name within the given JavaClassDescriptor. * * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. */ static JSBool add_java_field_to_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, jstring field_name_jstr, jobject java_field, /* a java.lang.reflect.Field */ jint modifiers) { jclass fieldType; jfieldID fieldID; jclass java_class; JSBool is_static_field; JavaMemberDescriptor *member_descriptor = NULL; const char *sig_cstr = NULL; const char *field_name = NULL; JavaSignature *signature = NULL; JavaFieldSpec *field_spec = NULL; is_static_field = modifiers & ACC_STATIC; if (is_static_field) { member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); } else { member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); } if (!member_descriptor) goto error; field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec)); if (!field_spec) goto error; field_spec->modifiers = modifiers; /* Get the Java class corresponding to the type of the field */ fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType); if (!fieldType) { jsj_UnexpectedJavaError(cx, jEnv, "Unable to determine type of field using" " java.lang.reflect.Field.getType()"); goto error; } signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType); (*jEnv)->DeleteLocalRef(jEnv, fieldType); if (!signature) goto error; field_spec->signature = signature; field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr); if (!field_name) goto error; field_spec->name = field_name; /* Compute the JNI-style (string-based) signature of the field type */ sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature); if (!sig_cstr) goto error; /* Compute the JNI fieldID and cache it for quick field access */ java_class = class_descriptor->java_class; if (is_static_field) fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr); else fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr); if (!fieldID) { jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java field ID for class %s, field %s (sig=%s)", class_descriptor->name, field_name, sig_cstr); goto error; } field_spec->fieldID = fieldID; JS_free(cx, (char*)sig_cstr); member_descriptor->field = field_spec; /* Success */ return JS_TRUE; error: if (field_spec) { JS_FREE_IF(cx, (char*)field_spec->name); JS_free(cx, field_spec); } JS_FREE_IF(cx, (char*)sig_cstr); if (signature) jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature); return JS_FALSE; }