jsj_method.c
来自「一个基于alice开发的机器人」· C语言 代码 · 共 1,813 行 · 第 1/5 页
C
1,813 行
/* -*- 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.
*/
void
jsj_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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?