📄 jsj_method.c
字号:
error: if (arg_classes) (*jEnv)->DeleteLocalRef(jEnv, arg_classes); jsj_PurgeJavaMethodSignature(cx, jEnv, method_signature); return NULL;}/* * Compute a JNI-style (string) signature for the given method, e.g. the method * "String MyFunc(int, byte)" is translated to "(IB)Ljava/lang/String;". * * If an error is encountered, NULL is returned and the error reporter is called. */const char *jsj_ConvertJavaMethodSignatureToString(JSContext *cx, JavaMethodSignature *method_signature){ JavaSignature **arg_signatures, *return_val_signature; const char *arg_sigs_cstr; const char *return_val_sig_cstr; const char *sig_cstr; arg_signatures = method_signature->arg_signatures; return_val_signature = method_signature->return_val_signature; /* Convert the method argument signatures to a C-string */ arg_sigs_cstr = NULL; if (arg_signatures) { arg_sigs_cstr = convert_java_method_arg_signatures_to_string(cx, arg_signatures, method_signature->num_args); if (!arg_sigs_cstr) return NULL; } /* Convert the method return value signature to a C-string */ return_val_sig_cstr = jsj_ConvertJavaSignatureToString(cx, return_val_signature); if (!return_val_sig_cstr) { free((void*)arg_sigs_cstr); return NULL; } /* Compose method arg signatures string and return val signature string */ if (arg_sigs_cstr) { sig_cstr = JS_smprintf("(%s)%s", arg_sigs_cstr, return_val_sig_cstr); free((void*)arg_sigs_cstr); } else { sig_cstr = JS_smprintf("()%s", return_val_sig_cstr); } free((void*)return_val_sig_cstr); if (!sig_cstr) { JS_ReportOutOfMemory(cx); return NULL; } return sig_cstr;}static JSBooladd_java_method_to_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, jstring method_name_jstr, jobject java_method, JSBool is_static_method, JSBool is_constructor){ jmethodID methodID; JSFunction *fun; jclass java_class = class_descriptor->java_class; JavaMemberDescriptor *member_descriptor = NULL; const char *sig_cstr = NULL; const char *method_name = NULL; JavaMethodSignature *signature = NULL; JavaMethodSpec **specp, *method_spec = NULL; if (is_constructor) { member_descriptor = jsj_GetJavaClassConstructors(cx, class_descriptor); } else { if (is_static_method) { member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); } else { member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); } fun = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0, JSFUN_BOUND_METHOD, NULL, member_descriptor->name); member_descriptor->invoke_func_obj = JS_GetFunctionObject(fun); JS_AddNamedRoot(cx, &member_descriptor->invoke_func_obj, "&member_descriptor->invoke_func_obj"); } if (!member_descriptor) return JS_FALSE; method_spec = (JavaMethodSpec*)JS_malloc(cx, sizeof(JavaMethodSpec)); if (!method_spec) goto error; memset(method_spec, 0, sizeof(JavaMethodSpec)); signature = jsj_InitJavaMethodSignature(cx, jEnv, java_method, &method_spec->signature); if (!signature) goto error; method_name = JS_strdup(cx, member_descriptor->name); if (!method_name) goto error; method_spec->name = method_name; sig_cstr = jsj_ConvertJavaMethodSignatureToString(cx, signature); if (!sig_cstr) goto error; if (is_static_method) methodID = (*jEnv)->GetStaticMethodID(jEnv, java_class, method_name, sig_cstr); else methodID = (*jEnv)->GetMethodID(jEnv, java_class, method_name, sig_cstr); method_spec->methodID = methodID; if (!methodID) { jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java method ID for %s.%s() (sig=%s)", class_descriptor->name, method_name, sig_cstr); goto error; } JS_free(cx, (char*)sig_cstr); /* Add method to end of list of overloaded methods for this class member */ specp = &member_descriptor->methods; while (*specp) { specp = &(*specp)->next; } *specp = method_spec; return JS_TRUE;error: if (method_spec) JS_FREE_IF(cx, (char*)method_spec->name); JS_FREE_IF(cx, (char*)sig_cstr); if (signature) jsj_PurgeJavaMethodSignature(cx, jEnv, signature); JS_FREE_IF(cx, method_spec); return JS_FALSE;}JSBool jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, JSBool reflect_only_static_methods){ jarray joMethodArray, joConstructorArray; jsize num_methods, num_constructors; int i; jclass java_class; JSBool ok, reflect_only_instance_methods; reflect_only_instance_methods = !reflect_only_static_methods; /* Get a java array of java.lang.reflect.Method objects, by calling java.lang.Class.getMethods(). */ java_class = class_descriptor->java_class; joMethodArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getMethods); if (!joMethodArray) { jsj_UnexpectedJavaError(cx, jEnv, "Can't determine Java object's methods " "using java.lang.Class.getMethods()"); return JS_FALSE; } /* Iterate over the class methods */ num_methods = (*jEnv)->GetArrayLength(jEnv, joMethodArray); for (i = 0; i < num_methods; i++) { jstring method_name_jstr; /* Get the i'th reflected method */ jobject java_method = (*jEnv)->GetObjectArrayElement(jEnv, joMethodArray, i); /* Get the method modifiers, eg static, public, private, etc. */ jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_method, jlrMethod_getModifiers); /* Don't allow access to private or protected Java methods. */ if (!(modifiers & ACC_PUBLIC)) goto dont_reflect_method; /* Abstract methods can't be invoked */ if (modifiers & ACC_ABSTRACT) goto dont_reflect_method; /* Reflect all instance methods or all static methods, but not both */ if (reflect_only_static_methods != ((modifiers & ACC_STATIC) != 0)) goto dont_reflect_method; /* Add a JavaMethodSpec object to the JavaClassDescriptor */ method_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_method, jlrMethod_getName); ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, method_name_jstr, java_method, reflect_only_static_methods, JS_FALSE); (*jEnv)->DeleteLocalRef(jEnv, method_name_jstr); if (!ok) { (*jEnv)->DeleteLocalRef(jEnv, java_method); (*jEnv)->DeleteLocalRef(jEnv, joMethodArray); return JS_FALSE; }dont_reflect_method: (*jEnv)->DeleteLocalRef(jEnv, java_method); } (*jEnv)->DeleteLocalRef(jEnv, joMethodArray); if (reflect_only_instance_methods) return JS_TRUE; joConstructorArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getConstructors); if (!joConstructorArray) { jsj_UnexpectedJavaError(cx, jEnv, "internal error: " "Can't determine Java class's constructors " "using java.lang.Class.getConstructors()"); return JS_FALSE; } /* Iterate over the class constructors */ num_constructors = (*jEnv)->GetArrayLength(jEnv, joConstructorArray); for (i = 0; i < num_constructors; i++) { /* Get the i'th reflected constructor */ jobject java_constructor = (*jEnv)->GetObjectArrayElement(jEnv, joConstructorArray, i); /* Get the method modifiers, eg public, private, etc. */ jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_constructor, jlrConstructor_getModifiers); /* Don't allow access to private or protected Java methods. */ if (!(modifiers & ACC_PUBLIC)) goto dont_reflect_constructor; /* Add a JavaMethodSpec object to the JavaClassDescriptor */ ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, NULL, java_constructor, JS_FALSE, JS_TRUE); if (!ok) { (*jEnv)->DeleteLocalRef(jEnv, joConstructorArray); (*jEnv)->DeleteLocalRef(jEnv, java_constructor); return JS_FALSE; }dont_reflect_constructor: (*jEnv)->DeleteLocalRef(jEnv, java_constructor); } (*jEnv)->DeleteLocalRef(jEnv, joConstructorArray); return JS_TRUE;}/* * Free up a JavaMethodSpec and all its resources. */voidjsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec){ if (!method_spec->is_alias) { JS_FREE_IF(cx, (char*)method_spec->name); jsj_PurgeJavaMethodSignature(cx, jEnv, &method_spec->signature); } JS_free(cx, method_spec);}static JavaMethodSpec *copy_java_method_descriptor(JSContext *cx, JavaMethodSpec *method){ JavaMethodSpec *copy; copy = (JavaMethodSpec*)JS_malloc(cx, sizeof(JavaMethodSpec)); if (!copy) return NULL; memcpy(copy, method, sizeof(JavaMethodSpec)); copy->next = NULL; copy->is_alias = JS_TRUE; return copy;}/* * See if a reference to a JavaObject/JavaClass's property looks like the * explicit resolution of an overloaded method, e.g. * java.lang.String["max(double,double)"]. If so, add a new member * (JavaMemberDescriptor) to the object that is an alias for the resolved * method. */JavaMemberDescriptor *jsj_ResolveExplicitMethod(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, jsid method_name_id, JSBool is_static){ JavaMethodSpec *method; JavaMemberDescriptor *member_descriptor; JavaMethodSignature *ms; JSString *simple_name_jsstr; JSFunction *fun; JSBool is_constructor; int left_paren; const char *sig_cstr, *method_name; char *arg_start; jsid id; jsval method_name_jsval; /* * Get the simple name of the explicit method, i.e. get "cos" from * "cos(double)", and use it to create a new JS string. */ JS_IdToValue(cx, method_name_id, &method_name_jsval); method_name = JS_GetStringBytes(JSVAL_TO_STRING(method_name_jsval)); arg_start = strchr(method_name, '('); /* Skip until '(' */ /* If no left-paren, then this is not a case of explicit method resolution */ if (!arg_start) return NULL; /* Left-paren must be first character for constructors */ is_constructor = (is_static && (arg_start == method_name)); left_paren = arg_start - method_name; simple_name_jsstr = JS_NewStringCopyN(cx, method_name, left_paren); if (!simple_name_jsstr) return NULL; /* Find all the methods in the same class with the same simple name */ JS_ValueToId(cx, STRING_TO_JSVAL(simple_name_jsstr), &id); if (is_constructor) member_descriptor = jsj_LookupJavaClassConstructors(cx, jEnv, class_descriptor); else if (is_static) member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); else member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); if (!member_descriptor) /* No member with matching simple name ? */ return NULL; /* * Do a UTF8 comparison of method signatures with all methods of the same name, * so as to discover a method which exactly matches the specified argument types. */ if (!strlen(arg_start + 1)) return NULL; arg_start = JS_strdup(cx, arg_start + 1); if (!arg_start) return NULL; arg_start[strlen(arg_start) - 1] = '\0'; /* Get rid of ')' */ sig_cstr = NULL; /* Quiet gcc warning about uninitialized variable */ for (method = member_descriptor->methods; method; method = method->next) { ms = &method->signature; sig_cstr = convert_java_method_arg_signatures_to_hr_string(cx, ms->arg_signatures, ms->num_args, JS_FALSE); if (!sig_cstr) return NULL; if (!strcmp(sig_cstr, arg_start)) break; JS_free(cx, (void*)sig_cstr); } JS_free(cx, arg_start); if (!method) return NULL; JS_free(cx, (void*)sig_cstr); /* Don't bother doing anything if the method isn't overloaded */ if (!member_descriptor->methods->next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -