📄 jsj_method.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * This Original Code has been modified by IBM Corporation. Modifications made * by IBM described herein are Copyright (c) International Business Machines * Corporation, 2000. * Modifications to Mozilla code or documentation identified per MPL Section 3.3 * * Date Modified by Description of modification * 04/20/2000 IBM Corp. OS/2 VisualAge build. * * ***** END LICENSE BLOCK ***** *//* * This file is part of the Java-vendor-neutral implementation of LiveConnect * * It contains the code used to reflect Java methods as properties of * JavaObject objects and the code to invoke those methods. * */#include <stdlib.h>#include <string.h>#include "jsj_private.h" /* LiveConnect internals */#include "jsjava.h" /* LiveConnect external API */#include "jsclist.h" /* Circular linked lists *//* A list of Java methods */typedef JSCList MethodList;/* An element in a list of Java methods */typedef struct MethodListElement { JSCList linkage; JavaMethodSpec *method;} MethodListElement;/* * This is the return value of functions which compare either two types or two * method signatures to see if either is "preferred" when converting from * specified JavaScript value(s). */typedef enum JSJTypePreference { JSJPREF_FIRST_ARG = 1, /* First argument preferred */ JSJPREF_SECOND_ARG = 2, /* Second argument preferred */ JSJPREF_AMBIGUOUS = 3 /* Neither preferred over the other */} JSJTypePreference;/* * Classification of JS types with slightly different granularity than JSType. * This is used to resolve among overloaded Java methods. */typedef enum JSJType { JSJTYPE_VOID, /* undefined */ JSJTYPE_BOOLEAN, /* boolean */ JSJTYPE_NUMBER, /* number */ JSJTYPE_STRING, /* string */ JSJTYPE_NULL, /* null */ JSJTYPE_JAVACLASS, /* JavaClass */ JSJTYPE_JAVAOBJECT, /* JavaObject */ JSJTYPE_JAVAARRAY, /* JavaArray */ JSJTYPE_JSARRAY, /* JS Array */ JSJTYPE_OBJECT, /* Any other JS Object, including functions */ JSJTYPE_LIMIT} JSJType;/* * A helper function for jsj_ConvertJavaMethodSignatureToString(): * Compute JNI-style (string) signatures for an array of JavaSignature objects * and concatenate the results into a single string. * * If an error is encountered, NULL is returned and the error reporter is called. */static const char *convert_java_method_arg_signatures_to_string(JSContext *cx, JavaSignature **arg_signatures, int num_args){ const char *first_arg_signature, *rest_arg_signatures, *sig; JavaSignature **rest_args; /* Convert the first method argument in the array to a string */ first_arg_signature = jsj_ConvertJavaSignatureToString(cx, arg_signatures[0]); if (!first_arg_signature) return NULL; /* If this is the last method argument in the array, we're done. */ if (num_args == 1) return first_arg_signature; /* Convert the remaining method arguments to a string */ rest_args = &arg_signatures[1]; rest_arg_signatures = convert_java_method_arg_signatures_to_string(cx, rest_args, num_args - 1); if (!rest_arg_signatures) { free((void*)first_arg_signature); return NULL; } /* Concatenate the signature string of this argument with the signature strings of all the remaining arguments. */ sig = JS_smprintf("%s%s", first_arg_signature, rest_arg_signatures); free((void*)first_arg_signature); free((void*)rest_arg_signatures); if (!sig) { JS_ReportOutOfMemory(cx); return NULL; } return sig;}/* * A helper function for jsj_ConvertJavaMethodSignatureToHRString(): * Compute human-readable string signatures for an array of JavaSignatures * and concatenate the results into a single string. * * If an error is encountered, NULL is returned and the error reporter is called. */static const char *convert_java_method_arg_signatures_to_hr_string(JSContext *cx, JavaSignature **arg_signatures, int num_args, JSBool whitespace){ const char *first_arg_signature, *rest_arg_signatures, *sig, *separator; JavaSignature **rest_args; if (num_args == 0) return strdup(""); /* Convert the first method argument in the array to a string */ first_arg_signature = jsj_ConvertJavaSignatureToHRString(cx, arg_signatures[0]); if (!first_arg_signature) return NULL; /* If this is the last method argument in the array, we're done. */ if (num_args == 1) return first_arg_signature; /* Convert the remaining method arguments to a string */ rest_args = &arg_signatures[1]; rest_arg_signatures = convert_java_method_arg_signatures_to_hr_string(cx, rest_args, num_args - 1, whitespace); if (!rest_arg_signatures) { free((void*)first_arg_signature); return NULL; } /* Concatenate the signature string of this argument with the signature strings of all the remaining arguments. */ separator = whitespace ? " " : ""; sig = JS_smprintf("%s,%s%s", first_arg_signature, separator, rest_arg_signatures); free((void*)first_arg_signature); free((void*)rest_arg_signatures); if (!sig) { JS_ReportOutOfMemory(cx); return NULL; } return sig;}/* * Compute a string signature for the given method using the same type names * that appear in Java source files, e.g. "int[][]", rather than the JNI-style * type strings that are provided by the functions above. An example return * value might be "String MyFunc(int, byte, char[][], java.lang.String)". * * If an error is encountered, NULL is returned and the error reporter is called. */const char *jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx, const char *method_name, 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 = convert_java_method_arg_signatures_to_hr_string(cx, arg_signatures, method_signature->num_args, JS_TRUE); if (!arg_sigs_cstr) return NULL; /* Convert the method return value signature to a C-string */ return_val_sig_cstr = jsj_ConvertJavaSignatureToHRString(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 */ sig_cstr = JS_smprintf("%s %s(%s)", return_val_sig_cstr, method_name, arg_sigs_cstr); free((void*)arg_sigs_cstr); free((void*)return_val_sig_cstr); if (!sig_cstr) { JS_ReportOutOfMemory(cx); return NULL; } return sig_cstr;}/* * Destroy the sub-structure of a JavaMethodSignature object without free'ing * the method signature itself. */voidjsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *method_signature){ int i, num_args; JavaSignature **arg_signatures; if (!method_signature) /* Paranoia */ return; /* Free the method argument signatures */ num_args = method_signature->num_args; arg_signatures = method_signature->arg_signatures; for (i = 0; i < num_args; i++) jsj_ReleaseJavaClassDescriptor(cx, jEnv, arg_signatures[i]); if (arg_signatures) JS_free(cx, arg_signatures); /* Free the return type signature */ if (method_signature->return_val_signature) jsj_ReleaseJavaClassDescriptor(cx, jEnv, method_signature->return_val_signature);}/* * Fill in the members of a JavaMethodSignature object using the method * argument, which can be either an instance of either java.lang.reflect.Method * or java.lang.reflect.Constructor. * * With normal completion, return the original method_signature argument. * If an error occurs, return NULL and call the error reporter. */JavaMethodSignature *jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, jobject method, JavaMethodSignature *method_signature){ int i; jboolean is_constructor; jclass return_val_class; jsize num_args; JavaSignature *return_val_signature; jarray arg_classes; jmethodID getParameterTypes; memset(method_signature, 0, sizeof (JavaMethodSignature)); is_constructor = (*jEnv)->IsInstanceOf(jEnv, method, jlrConstructor); /* Get a Java array that lists the class of each of the method's arguments */ if (is_constructor) getParameterTypes = jlrConstructor_getParameterTypes; else getParameterTypes = jlrMethod_getParameterTypes; arg_classes = (*jEnv)->CallObjectMethod(jEnv, method, getParameterTypes); if (!arg_classes) { jsj_UnexpectedJavaError(cx, jEnv, "Can't determine argument signature of method"); goto error; } /* Compute the number of method arguments */ num_args = jsj_GetJavaArrayLength(cx, jEnv, arg_classes); if (num_args < 0) goto error; method_signature->num_args = num_args; /* Build a JavaSignature array corresponding to the method's arguments */ if (num_args) { JavaSignature **arg_signatures; /* Allocate an array of JavaSignatures, one for each method argument */ size_t arg_signatures_size = num_args * sizeof(JavaSignature *); arg_signatures = (JavaSignature **)JS_malloc(cx, arg_signatures_size); if (!arg_signatures) goto error; memset(arg_signatures, 0, arg_signatures_size); method_signature->arg_signatures = arg_signatures; /* Build an array of JavaSignature objects, each of which corresponds to the type of an individual method argument. */ for (i = 0; i < num_args; i++) { JavaSignature *a; jclass arg_class = (*jEnv)->GetObjectArrayElement(jEnv, arg_classes, i); a = arg_signatures[i] = jsj_GetJavaClassDescriptor(cx, jEnv, arg_class); (*jEnv)->DeleteLocalRef(jEnv, arg_class); if (!a) { jsj_UnexpectedJavaError(cx, jEnv, "Could not determine Java class " "signature using java.lang.reflect"); goto error; } } } /* Get the Java class of the method's return value */ if (is_constructor) { /* Constructors always have a "void" return type */ return_val_signature = jsj_GetJavaClassDescriptor(cx, jEnv, jlVoid_TYPE); } else { return_val_class = (*jEnv)->CallObjectMethod(jEnv, method, jlrMethod_getReturnType); if (!return_val_class) { jsj_UnexpectedJavaError(cx, jEnv, "Can't determine return type of method " "using java.lang.reflect.Method.getReturnType()"); goto error; } /* Build a JavaSignature object corresponding to the method's return value */ return_val_signature = jsj_GetJavaClassDescriptor(cx, jEnv, return_val_class); (*jEnv)->DeleteLocalRef(jEnv, return_val_class); } if (!return_val_signature) goto error; method_signature->return_val_signature = return_val_signature; (*jEnv)->DeleteLocalRef(jEnv, arg_classes); return method_signature;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -