Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Enumerations | Functions | Variables
jsj_method.c File Reference
#include <stdlib.h>
#include <string.h>
#include "jsj_private.h"
#include "jsjava.h"
#include "jsclist.h"

Go to the source code of this file.

Classes

struct  MethodListElement

Defines

#define CALL_JAVA_METHOD(type, member)

Typedefs

typedef JSCList MethodList
typedef struct MethodListElement MethodListElement
typedef enum JSJTypePreference JSJTypePreference
typedef enum JSJType JSJType

Enumerations

enum  JSJTypePreference { JSJPREF_FIRST_ARG = 1, JSJPREF_SECOND_ARG = 2, JSJPREF_AMBIGUOUS = 3 }
enum  JSJType {
  JSJTYPE_VOID, JSJTYPE_BOOLEAN, JSJTYPE_NUMBER, JSJTYPE_STRING,
  JSJTYPE_NULL, JSJTYPE_JAVACLASS, JSJTYPE_JAVAOBJECT, JSJTYPE_JAVAARRAY,
  JSJTYPE_JSARRAY, JSJTYPE_OBJECT, JSJTYPE_LIMIT
}

Functions

static const char * convert_java_method_arg_signatures_to_string (JSContext *cx, JavaSignature **arg_signatures, int num_args)
static const char * convert_java_method_arg_signatures_to_hr_string (JSContext *cx, JavaSignature **arg_signatures, int num_args, JSBool whitespace)
const char * jsj_ConvertJavaMethodSignatureToHRString (JSContext *cx, const char *method_name, JavaMethodSignature *method_signature)
void jsj_PurgeJavaMethodSignature (JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *method_signature)
JavaMethodSignaturejsj_InitJavaMethodSignature (JSContext *cx, JNIEnv *jEnv, jobject method, JavaMethodSignature *method_signature)
const char * jsj_ConvertJavaMethodSignatureToString (JSContext *cx, JavaMethodSignature *method_signature)
static JSBool add_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)
JSBool jsj_ReflectJavaMethods (JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, JSBool reflect_only_static_methods)
void jsj_DestroyMethodSpec (JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec)
static JavaMethodSpeccopy_java_method_descriptor (JSContext *cx, JavaMethodSpec *method)
JavaMemberDescriptorjsj_ResolveExplicitMethod (JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, jsid method_name_id, JSBool is_static)
static const char * get_js_arg_types_as_string (JSContext *cx, uintN argc, jsval *argv)
static void report_method_match_failure (JSContext *cx, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, JSBool is_static_method, uintN argc, jsval *argv)
static void report_ambiguous_method_match (JSContext *cx, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, MethodList *ambiguous_methods, JSBool is_static_method, uintN argc, jsval *argv)
static JSJType compute_jsj_type (JSContext *cx, jsval v)
static JSBool method_signature_matches_JS_args (JSContext *cx, JNIEnv *jEnv, uintN argc, jsval *argv, JavaMethodSignature *method_signature)
static JSJTypePreference preferred_conversion (JSContext *cx, JNIEnv *jEnv, jsval js_val, JavaClassDescriptor *descriptor1, JavaClassDescriptor *descriptor2)
static JSJTypePreference method_preferred (JSContext *cx, JNIEnv *jEnv, jsval *argv, JavaMethodSignature *method_signature1, JavaMethodSignature *method_signature2)
static JavaMethodSpecresolve_overloaded_method (JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, JSBool is_static_method, uintN argc, jsval *argv)
static jvalueconvert_JS_method_args_to_java_argv (JSContext *cx, JNIEnv *jEnv, jsval *argv, JavaMethodSpec *method, JSBool **localvp)
static JSBool invoke_java_method (JSContext *cx, JSJavaThreadState *jsj_env, jobject java_class_or_instance, JavaClassDescriptor *class_descriptor, JavaMethodSpec *method, JSBool is_static_method, jsval *argv, jsval *vp)
static JSBool invoke_overloaded_java_method (JSContext *cx, JSJavaThreadState *jsj_env, JavaMemberDescriptor *member, JSBool is_static_method, jobject java_class_or_instance, JavaClassDescriptor *class_descriptor, uintN argc, jsval *argv, jsval *vp)
static JSBool invoke_java_constructor (JSContext *cx, JSJavaThreadState *jsj_env, jclass java_class, JavaMethodSpec *method, jsval *argv, jsval *vp)
static JSBool invoke_overloaded_java_constructor (JSContext *cx, JSJavaThreadState *jsj_env, JavaMemberDescriptor *member, JavaClassDescriptor *class_descriptor, uintN argc, jsval *argv, jsval *vp)
static JSBool java_constructor_wrapper (JSContext *cx, JSJavaThreadState *jsj_env, JavaMemberDescriptor *member_descriptor, JavaClassDescriptor *class_descriptor, uintN argc, jsval *argv, jsval *vp)
 jsj_JavaConstructorWrapper (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
static JSBool static_method_wrapper (JSContext *cx, JSJavaThreadState *jsj_env, JavaClassDescriptor *class_descriptor, jsid id, uintN argc, jsval *argv, jsval *vp)
 jsj_JavaStaticMethodWrapper (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)
 jsj_JavaInstanceMethodWrapper (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *vp)

Variables

static int rank_table [JSJTYPE_LIMIT][JAVA_SIGNATURE_LIMIT]

Class Documentation

struct MethodListElement

Definition at line 67 of file jsj_method.c.

Collaboration diagram for MethodListElement:
Class Members
JSCList linkage
JavaMethodSpec * method

Define Documentation

#define CALL_JAVA_METHOD (   type,
  member 
)
Value:
JS_BEGIN_MACRO                                                           \
    if (is_static_method) {                                                  \
        java_value.member = (*jEnv)->CallStatic##type##MethodA(jEnv, java_class, methodID, jargv);\
    } else {                                                                 \
        java_value.member = (*jEnv)->Call##type##MethodA(jEnv, java_object, methodID, jargv);\
    }                                                                        \
    if ((*jEnv)->ExceptionOccurred(jEnv)) {                                  \
        jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()",        \
                            class_descriptor->name, method->name);           \
        error_occurred = JS_TRUE;                                            \
        goto out;                                                            \
    }                                                                        \
    JS_END_MACRO

Typedef Documentation

typedef enum JSJType JSJType

Definition at line 64 of file jsj_method.c.


Enumeration Type Documentation

enum JSJType
Enumerator:
JSJTYPE_VOID 
JSJTYPE_BOOLEAN 
JSJTYPE_NUMBER 
JSJTYPE_STRING 
JSJTYPE_NULL 
JSJTYPE_JAVACLASS 
JSJTYPE_JAVAOBJECT 
JSJTYPE_JAVAARRAY 
JSJTYPE_JSARRAY 
JSJTYPE_OBJECT 
JSJTYPE_LIMIT 

Definition at line 87 of file jsj_method.c.

                     {
    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;
Enumerator:
JSJPREF_FIRST_ARG 
JSJPREF_SECOND_ARG 
JSJPREF_AMBIGUOUS 

Definition at line 77 of file jsj_method.c.

                               {
    JSJPREF_FIRST_ARG  = 1,       /* First argument preferred */
    JSJPREF_SECOND_ARG = 2,       /* Second argument preferred */
    JSJPREF_AMBIGUOUS  = 3        /* Neither preferred over the other */
} JSJTypePreference;

Function Documentation

static JSBool add_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 
) [static]

Definition at line 428 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSJType compute_jsj_type ( JSContext cx,
jsval  v 
) [static]

Definition at line 959 of file jsj_method.c.

{
    JSObject *js_obj;

    if (JSVAL_IS_OBJECT(v)) {
        if (JSVAL_IS_NULL(v))
            return JSJTYPE_NULL;
        js_obj = JSVAL_TO_OBJECT(v);
        if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0))
           return JSJTYPE_JAVAOBJECT;
        if (JS_InstanceOf(cx, js_obj, &JavaArray_class, 0))
            return JSJTYPE_JAVAARRAY;
        if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0))
            return JSJTYPE_JAVACLASS;
        if (JS_IsArrayObject(cx, js_obj))
            return JSJTYPE_JSARRAY;
        return JSJTYPE_OBJECT;
    } else if (JSVAL_IS_NUMBER(v)) {
       return JSJTYPE_NUMBER;
    } else if (JSVAL_IS_STRING(v)) {
       return JSJTYPE_STRING;
    } else if (JSVAL_IS_BOOLEAN(v)) {
       return JSJTYPE_BOOLEAN;
    } else if (JSVAL_IS_VOID(v)) {
       return JSJTYPE_VOID;
    }
    JS_ASSERT(0);   /* Unknown JS type ! */
    return JSJTYPE_VOID;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* convert_java_method_arg_signatures_to_hr_string ( JSContext cx,
JavaSignature **  arg_signatures,
int  num_args,
JSBool  whitespace 
) [static]

Definition at line 155 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* convert_java_method_arg_signatures_to_string ( JSContext cx,
JavaSignature **  arg_signatures,
int  num_args 
) [static]

Definition at line 109 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static jvalue* convert_JS_method_args_to_java_argv ( JSContext cx,
JNIEnv jEnv,
jsval argv,
JavaMethodSpec method,
JSBool **  localvp 
) [static]

Definition at line 1326 of file jsj_method.c.

{
    jvalue *jargv;
    JSBool ok, *localv;
    uintN i, argc;
    JavaSignature **arg_signatures;
    JavaMethodSignature *signature;
    
    
    signature = &method->signature;
    argc = signature->num_args;
    JS_ASSERT(argc != 0);
    arg_signatures = signature->arg_signatures;
    
    jargv = (jvalue *)JS_malloc(cx, sizeof(jvalue) * argc);
    
    if (!jargv)
        return NULL;

    /*
     * Allocate an array that contains a flag for each argument, indicating whether
     * or not the conversion from a JS value to a Java value resulted in a new
     * JNI local reference.
     */
    localv = (JSBool *)JS_malloc(cx, sizeof(JSBool) * argc);
    *localvp = localv;
    if (!localv) {
        JS_free(cx, jargv);
        return NULL;
    }
 
    for (i = 0; i < argc; i++) {
        int dummy_cost;
        
        ok = jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signatures[i],
                                           &dummy_cost, &jargv[i], &localv[i]);
        if (!ok) {
            JS_free(cx, jargv);
            JS_free(cx, localv);
            *localvp = NULL;
            return NULL;
        }
    }

    return jargv;
}  

Here is the call graph for this function:

Here is the caller graph for this function:

static JavaMethodSpec* copy_java_method_descriptor ( JSContext cx,
JavaMethodSpec method 
) [static]

Definition at line 635 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static const char* get_js_arg_types_as_string ( JSContext cx,
uintN  argc,
jsval argv 
) [static]

Definition at line 784 of file jsj_method.c.

{
    uintN i;
    const char *arg_type, *arg_string, *tmp;

    if (argc == 0)
        return strdup("()");
    
    arg_string = strdup("(");
    if (!arg_string)
        goto out_of_memory;
    for (i = 0; i < argc; i++) {
        arg_type = JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i]));
        tmp = JS_smprintf("%s%s%s%s", arg_string,  i ? ", " : "", arg_type,
                         (i == argc-1) ? ")" : "");
        free((char*)arg_string);
        if (!tmp)
            goto out_of_memory;
        arg_string = tmp;
    }

    return arg_string;

out_of_memory:
    JS_ReportOutOfMemory(cx);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool invoke_java_constructor ( JSContext cx,
JSJavaThreadState jsj_env,
jclass  java_class,
JavaMethodSpec method,
jsval argv,
jsval vp 
) [static]

Definition at line 1548 of file jsj_method.c.

{
    jvalue *jargv;
    uintN argc, i;
    jobject java_object;
    jmethodID methodID;
    JavaMethodSignature *signature;
    JNIEnv *jEnv;
    JSBool *localv;
    JSBool success, error_occurred;
    java_object = NULL;         /* Stifle gcc uninitialized variable warning */

    success = error_occurred = JS_FALSE;
    
    methodID = method->methodID;
    signature = &method->signature;
    argc = signature->num_args;

    jEnv = jsj_env->jEnv;

    jargv = NULL;
    localv = NULL;
    if (argc) {
        jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv);
        if (!jargv) {
            error_occurred = JS_TRUE;
            goto out;
        }
    }

    /* Prevent deadlocking if we re-enter JS on another thread as a result of a Java
       method call and that new thread wants to perform a GC. */
#ifdef JSJ_THREADSAFE
    JS_EndRequest(cx);
#endif

    /* Call the constructor */
    java_object = (*jEnv)->NewObjectA(jEnv, java_class, methodID, jargv);

#ifdef JSJ_THREADSAFE
    JS_BeginRequest(cx);
#endif

    if (!java_object) {
        jsj_ReportJavaError(cx, jEnv, "Error while constructing instance of %s",
                            jsj_GetJavaClassName(cx, jEnv, java_class));
        error_occurred = JS_TRUE;
        goto out;
    }

out:
    if (localv) {
        for (i = 0; i < argc; i++) {
            if (localv[i])
                (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
        }
        JS_free(cx, localv);
    }
    if (jargv)
       JS_free(cx, jargv);
        
    if (!error_occurred)
        success = jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_object, vp);
    (*jEnv)->DeleteLocalRef(jEnv, java_object);
    return success;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool invoke_java_method ( JSContext cx,
JSJavaThreadState jsj_env,
jobject  java_class_or_instance,
JavaClassDescriptor class_descriptor,
JavaMethodSpec method,
JSBool  is_static_method,
jsval argv,
jsval vp 
) [static]

Definition at line 1375 of file jsj_method.c.

{
    jvalue java_value;
    jvalue *jargv;
    uintN argc, i;
    jobject java_object;
    jclass java_class;
    jmethodID methodID;
    JavaMethodSignature *signature;
    JavaSignature *return_val_signature;
    JNIEnv *jEnv;
    JSBool *localv, error_occurred, success;

    success = error_occurred = JS_FALSE;
    return_val_signature = NULL;    /* Quiet gcc uninitialized variable warning */

    methodID = method->methodID;
    signature = &method->signature;
    argc = signature->num_args;

    jEnv = jsj_env->jEnv;

    if (is_static_method) {
        java_object = NULL;
        java_class = java_class_or_instance;
    } else {
        java_object = java_class_or_instance;
        java_class = NULL;
    }

    jargv = NULL;
    localv = NULL;
    if (argc) {
        jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv);
        if (!jargv) {
            error_occurred = JS_TRUE;
            goto out;
        }
    }

    /* Prevent deadlocking if we re-enter JS on another thread as a result of a Java
       method call and that new thread wants to perform a GC. */
#ifdef JSJ_THREADSAFE
    JS_EndRequest(cx);
#endif

#define CALL_JAVA_METHOD(type, member)                                       \
    JS_BEGIN_MACRO                                                           \
    if (is_static_method) {                                                  \
        java_value.member = (*jEnv)->CallStatic##type##MethodA(jEnv, java_class, methodID, jargv);\
    } else {                                                                 \
        java_value.member = (*jEnv)->Call##type##MethodA(jEnv, java_object, methodID, jargv);\
    }                                                                        \
    if ((*jEnv)->ExceptionOccurred(jEnv)) {                                  \
        jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()",        \
                            class_descriptor->name, method->name);           \
        error_occurred = JS_TRUE;                                            \
        goto out;                                                            \
    }                                                                        \
    JS_END_MACRO

    return_val_signature = signature->return_val_signature;
    switch(return_val_signature->type) {
    case JAVA_SIGNATURE_BYTE:
        CALL_JAVA_METHOD(Byte, b);
        break;

    case JAVA_SIGNATURE_CHAR:
        CALL_JAVA_METHOD(Char, c);
        break;
    
    case JAVA_SIGNATURE_FLOAT:
        CALL_JAVA_METHOD(Float, f);
        break;
    
    case JAVA_SIGNATURE_DOUBLE:
        CALL_JAVA_METHOD(Double, d);
        break;
    
    case JAVA_SIGNATURE_INT:
        CALL_JAVA_METHOD(Int, i);
        break;
    
    case JAVA_SIGNATURE_LONG:
        CALL_JAVA_METHOD(Long, j);
        break;
    
    case JAVA_SIGNATURE_SHORT:
        CALL_JAVA_METHOD(Short, s);
        break;
    
    case JAVA_SIGNATURE_BOOLEAN:
        CALL_JAVA_METHOD(Boolean, z);
        break;
    
    case JAVA_SIGNATURE_VOID:
        if (is_static_method)
            (*jEnv)->CallStaticVoidMethodA(jEnv, java_class, methodID, jargv);
        else
            (*jEnv)->CallVoidMethodA(jEnv, java_object, methodID, jargv);
        if ((*jEnv)->ExceptionOccurred(jEnv)) {
            jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()",
                                class_descriptor->name, method->name);
            error_occurred = JS_TRUE;
            goto out;
        }
        break;
        
    case JAVA_SIGNATURE_UNKNOWN:
        JS_ASSERT(0);
        error_occurred = JS_TRUE;
        goto out;
            
    /* Non-primitive (reference) type */
    default:
        JS_ASSERT(IS_REFERENCE_TYPE(return_val_signature->type));
        CALL_JAVA_METHOD(Object, l);
        break;
    }

out:

    if (localv) {
        for (i = 0; i < argc; i++) {
            if (localv[i])
                (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l);
        }
        JS_free(cx, localv);
    }
    if (jargv)
       JS_free(cx, jargv);

#ifdef JSJ_THREADSAFE
    JS_BeginRequest(cx);
#endif

    if (!error_occurred) {
        success = jsj_ConvertJavaValueToJSValue(cx, jEnv, return_val_signature, &java_value, vp);
        if (IS_REFERENCE_TYPE(return_val_signature->type))
            (*jEnv)->DeleteLocalRef(jEnv, java_value.l);
    }
    return success;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool invoke_overloaded_java_constructor ( JSContext cx,
JSJavaThreadState jsj_env,
JavaMemberDescriptor member,
JavaClassDescriptor class_descriptor,
uintN  argc,
jsval argv,
jsval vp 
) [static]

Definition at line 1620 of file jsj_method.c.

{
    jclass java_class;
    JavaMethodSpec *method;
    JNIEnv *jEnv;

    jEnv = jsj_env->jEnv;

    method = resolve_overloaded_method(cx, jEnv, member, class_descriptor, JS_TRUE, 
                                       argc, argv);
    if (!method)
        return JS_FALSE;

    java_class = class_descriptor->java_class;
    return invoke_java_constructor(cx, jsj_env, java_class, method, argv, vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool invoke_overloaded_java_method ( JSContext cx,
JSJavaThreadState jsj_env,
JavaMemberDescriptor member,
JSBool  is_static_method,
jobject  java_class_or_instance,
JavaClassDescriptor class_descriptor,
uintN  argc,
jsval argv,
jsval vp 
) [static]

Definition at line 1525 of file jsj_method.c.

{
    JavaMethodSpec *method;
    JNIEnv *jEnv;

    jEnv = jsj_env->jEnv;

    method = resolve_overloaded_method(cx, jEnv, member, class_descriptor,
                                       is_static_method, argc, argv);
    if (!method)
        return JS_FALSE;

    return invoke_java_method(cx, jsj_env, java_class_or_instance, class_descriptor, 
                              method, is_static_method, argv, vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool java_constructor_wrapper ( JSContext cx,
JSJavaThreadState jsj_env,
JavaMemberDescriptor member_descriptor,
JavaClassDescriptor class_descriptor,
uintN  argc,
jsval argv,
jsval vp 
) [static]

Definition at line 1643 of file jsj_method.c.

{
    jint modifiers;
    JNIEnv *jEnv;

    jEnv = jsj_env->jEnv;
    
    /* Get class/interface flags and check them */
    modifiers = class_descriptor->modifiers;
    if (modifiers & ACC_ABSTRACT) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                            JSJMSG_ABSTRACT_JCLASS, class_descriptor->name);
        return JS_FALSE;
    }
    if (modifiers & ACC_INTERFACE) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                            JSJMSG_IS_INTERFACE, class_descriptor->name);
        return JS_FALSE;
    }
    if ( !(modifiers & ACC_PUBLIC) ) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                            JSJMSG_NOT_PUBLIC, class_descriptor->name);
        return JS_FALSE;
    }
    
    if (!member_descriptor) {
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                            JSJMSG_NO_CONSTRUCTORS, class_descriptor->name);
        return JS_FALSE;
    }

    return invoke_overloaded_java_constructor(cx, jsj_env, member_descriptor,
                                              class_descriptor, argc, argv, vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* jsj_ConvertJavaMethodSignatureToHRString ( JSContext cx,
const char *  method_name,
JavaMethodSignature method_signature 
)

Definition at line 206 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 382 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void jsj_DestroyMethodSpec ( JSContext cx,
JNIEnv jEnv,
JavaMethodSpec method_spec 
)

Definition at line 625 of file jsj_method.c.

{
    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

JavaMethodSignature* jsj_InitJavaMethodSignature ( JSContext cx,
JNIEnv jEnv,
jobject  method,
JavaMethodSignature method_signature 
)

Definition at line 279 of file jsj_method.c.

{
    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;

error:

    if (arg_classes)
        (*jEnv)->DeleteLocalRef(jEnv, arg_classes);
    jsj_PurgeJavaMethodSignature(cx, jEnv, method_signature);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

jsj_JavaConstructorWrapper ( JSContext cx,
JSObject obj,
uintN  argc,
jsval argv,
jsval vp 
)

Definition at line 1682 of file jsj_method.c.

{
    JavaClassDescriptor *class_descriptor;
    JavaMemberDescriptor *member_descriptor;
    JSJavaThreadState *jsj_env;
    JNIEnv *jEnv;
    JSBool result;

    obj = JSVAL_TO_OBJECT(argv[-2]);
    class_descriptor = JS_GetPrivate(cx, obj);
    JS_ASSERT(class_descriptor);
    if (!class_descriptor)
        return JS_FALSE;

    /* XXX, workaround for bug 200016, all classes in sun.plugin package should not 
       be accessible in liveconnect.
       Ideally, this checking should be done in JPI side, but it's not going to happen 
       until Sun JRE 1.5.1 */
    if (strstr(class_descriptor->name, "sun.plugin.") == class_descriptor->name)
        return JS_FALSE;
  
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    member_descriptor = jsj_LookupJavaClassConstructors(cx, jEnv, class_descriptor);
    result = java_constructor_wrapper(cx, jsj_env, member_descriptor, 
                                      class_descriptor, argc, argv, vp);
    jsj_ExitJava(jsj_env);
    return result;
}

Here is the call graph for this function:

jsj_JavaInstanceMethodWrapper ( JSContext cx,
JSObject obj,
uintN  argc,
jsval argv,
jsval vp 
)

Definition at line 1776 of file jsj_method.c.

{
    JSFunction *function;
    JavaMemberDescriptor *member_descriptor;
    JavaObjectWrapper *java_wrapper;
    JavaClassDescriptor *class_descriptor;
    jsid id;
    jsval idval;
    JSJavaThreadState *jsj_env;
    JNIEnv *jEnv;
    jobject java_obj;
    JSBool result;
    
    java_wrapper = JS_GetPrivate(cx, obj);
    if (!java_wrapper)
        return JS_FALSE;
    java_obj = java_wrapper->java_obj;
    
    JS_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION);
    function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2]));
    idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function)));
    JS_ValueToId(cx, idval, &id);
    class_descriptor = java_wrapper->class_descriptor;
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    if (jaApplet && (*jEnv)->IsInstanceOf(jEnv, java_obj, jaApplet)) {
        jsj_JSIsCallingApplet = JS_TRUE;
    }

    /* Try to find an instance method with the given name first */
    member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id);
    if (member_descriptor)
        result = invoke_overloaded_java_method(cx, jsj_env, member_descriptor,
                                               JS_FALSE, java_obj, 
                                               class_descriptor, argc, argv, vp);

    /* If no instance method was found, try for a static method or constructor */
    else
       result = static_method_wrapper(cx, jsj_env, class_descriptor, id, argc, argv, vp);
    jsj_ExitJava(jsj_env);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

jsj_JavaStaticMethodWrapper ( JSContext cx,
JSObject obj,
uintN  argc,
jsval argv,
jsval vp 
)

Definition at line 1745 of file jsj_method.c.

{
    JSFunction *function;
    JavaClassDescriptor *class_descriptor;
    jsid id;
    jsval idval;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;
    
    class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor)
        return JS_FALSE;

    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    
    JS_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION);
    function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2]));
    idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function)));
    JS_ValueToId(cx, idval, &id);

    result = static_method_wrapper(cx, jsj_env, class_descriptor, id, argc, argv, vp);
    jsj_ExitJava(jsj_env);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void jsj_PurgeJavaMethodSignature ( JSContext cx,
JNIEnv jEnv,
JavaMethodSignature method_signature 
)

Definition at line 249 of file jsj_method.c.

{
    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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

JSBool jsj_ReflectJavaMethods ( JSContext cx,
JNIEnv jEnv,
JavaClassDescriptor class_descriptor,
JSBool  reflect_only_static_methods 
)

Definition at line 515 of file jsj_method.c.

{
    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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

JavaMemberDescriptor* jsj_ResolveExplicitMethod ( JSContext cx,
JNIEnv jEnv,
JavaClassDescriptor class_descriptor,
jsid  method_name_id,
JSBool  is_static 
)

Definition at line 656 of file jsj_method.c.

{
    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)
       return member_descriptor;

    /*
     * To speed up performance for future accesses, create a new member descriptor
     * with a name equal to the explicit method name, i.e. "cos(double)".
     */
    member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor));
    if (!member_descriptor)
        return NULL;
    memset(member_descriptor, 0, sizeof(JavaMemberDescriptor));

    member_descriptor->id = method_name_id;
    member_descriptor->name =
        JS_strdup(cx, is_constructor ? "<init>" : JS_GetStringBytes(simple_name_jsstr));
    if (!member_descriptor->name) {
        JS_free(cx, member_descriptor);
        return NULL;
    }

    member_descriptor->methods = copy_java_method_descriptor(cx, method);
    if (!member_descriptor->methods) {
       JS_free(cx, (void*)member_descriptor->name);
        JS_free(cx, member_descriptor);
        return NULL;
    }
 
    fun = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0,
                      JSFUN_BOUND_METHOD, NULL, method_name);
    member_descriptor->invoke_func_obj = JS_GetFunctionObject(fun);
    JS_AddNamedRoot(cx, &member_descriptor->invoke_func_obj,
                    "&member_descriptor->invoke_func_obj");

    /* THREADSAFETY */
    /* Add the new aliased member to the list of all members for the class */
    if (is_static) {
       member_descriptor->next = class_descriptor->static_members;
       class_descriptor->static_members = member_descriptor;
    } else {
       member_descriptor->next = class_descriptor->instance_members;
       class_descriptor->instance_members = member_descriptor;
    }

    return member_descriptor;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSJTypePreference method_preferred ( JSContext cx,
JNIEnv jEnv,
jsval argv,
JavaMethodSignature method_signature1,
JavaMethodSignature method_signature2 
) [static]

Definition at line 1174 of file jsj_method.c.

{
    int arg_index, argc, preference;
    jsval val;
    JavaSignature* *arg_signatures1;
    JavaSignature* *arg_signatures2;
    JavaSignature *arg_type1, *arg_type2;

    arg_signatures1 = method_signature1->arg_signatures;
    arg_signatures2 = method_signature2->arg_signatures;
    argc = method_signature1->num_args;
    JS_ASSERT(argc == method_signature2->num_args);

    preference = 0;
    for (arg_index = 0; arg_index < argc; arg_index++) {
        val = argv[arg_index];
        arg_type1 = *arg_signatures1++;
        arg_type2 = *arg_signatures2++;

        if (arg_type1 == arg_type2)
            continue;

        preference |= preferred_conversion(cx, jEnv, val, arg_type1, arg_type2);

        if ((JSJTypePreference)preference == JSJPREF_AMBIGUOUS)
            return JSJPREF_AMBIGUOUS;
    }
    return (JSJTypePreference)preference;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool method_signature_matches_JS_args ( JSContext cx,
JNIEnv jEnv,
uintN  argc,
jsval argv,
JavaMethodSignature method_signature 
) [static]

Definition at line 1023 of file jsj_method.c.

{
    uintN i;
    JavaClassDescriptor *descriptor;
    JavaObjectWrapper *java_wrapper;
    jclass java_class;
    jobject java_obj;
    JSObject *js_obj;
    JSJType js_type;
    jsval js_val;
    int rank;

    if (argc != (uintN)method_signature->num_args)
        return JS_FALSE;

    for (i = 0; i < argc; i++) {
        js_val = argv[i];
        js_type = compute_jsj_type(cx, js_val);
        descriptor = method_signature->arg_signatures[i];
        rank = rank_table[js_type][(int)descriptor->type - 2];

        /* Check for disallowed JS->Java conversion */
        if (rank == 99)
            return JS_FALSE;

        /* Check for special handling required by conversion from JavaObject */
        if (rank == 0) {
            java_class = descriptor->java_class;
        
            js_obj = JSVAL_TO_OBJECT(js_val);
            java_wrapper = JS_GetPrivate(cx, js_obj);
            java_obj = java_wrapper->java_obj;
        
            if (!(*jEnv)->IsInstanceOf(jEnv, java_obj, java_class))
                return JS_FALSE;
        }
    }

    return JS_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSJTypePreference preferred_conversion ( JSContext cx,
JNIEnv jEnv,
jsval  js_val,
JavaClassDescriptor descriptor1,
JavaClassDescriptor descriptor2 
) [static]

Definition at line 1111 of file jsj_method.c.

{
    JSJType js_type;
    int rank1, rank2;
    jclass java_class1, java_class2;
    JavaObjectWrapper *java_wrapper;
    jobject java_obj;
    JSObject *js_obj;
    
    js_type = compute_jsj_type(cx, js_val);
    rank1 = rank_table[js_type][(int)descriptor1->type - 2];
    rank2 = rank_table[js_type][(int)descriptor2->type - 2];
        
    /* Fast path for conversion from most JS types */  
    if (rank1 < rank2)
        return JSJPREF_FIRST_ARG;

    /*
     * Special logic is required for matching the classes of wrapped
     * Java objects.
     */
    if (rank2 == 0) {
        java_class1 = descriptor1->java_class;
        java_class2 = descriptor2->java_class;
        
        js_obj = JSVAL_TO_OBJECT(js_val);
        java_wrapper = JS_GetPrivate(cx, js_obj);
        java_obj = java_wrapper->java_obj;
        
        /* Unwrapped JavaObject must be compatible with Java arg type */
        if (!(*jEnv)->IsInstanceOf(jEnv, java_obj, java_class2))
            return JSJPREF_FIRST_ARG;

        /*
         * For JavaObject arguments, any compatible reference type is preferable
         * to any primitive Java type or to java.lang.String.
         */
        if (rank1 != 0)
            return JSJPREF_SECOND_ARG;
        
        /*
         * If argument of type descriptor1 is subclass of type descriptor 2, then
         * descriptor1 is preferred and vice-versa.
         */
        if ((*jEnv)->IsAssignableFrom(jEnv, java_class1, java_class2))
            return JSJPREF_FIRST_ARG;
        
        if ((*jEnv)->IsAssignableFrom(jEnv, java_class2, java_class1))
            return JSJPREF_SECOND_ARG;

        /* This can happen in unusual situations involving interface types. */
        return JSJPREF_AMBIGUOUS;
    }
    
    if (rank1 > rank2)
        return JSJPREF_SECOND_ARG;
    
    return JSJPREF_AMBIGUOUS;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void report_ambiguous_method_match ( JSContext cx,
JavaMemberDescriptor member_descriptor,
JavaClassDescriptor class_descriptor,
MethodList ambiguous_methods,
JSBool  is_static_method,
uintN  argc,
jsval argv 
) [static]

Definition at line 887 of file jsj_method.c.

{
    const char *err, *js_arg_string, *tmp, *method_str, *method_name;
    JSBool is_constructor;
    JavaMethodSpec *method;
    MethodListElement *method_list_element;

    err = NULL;
    is_constructor = (!strcmp(member_descriptor->name, "<init>"));

    js_arg_string = get_js_arg_types_as_string(cx, argc, argv);
    if (!js_arg_string)
        goto out_of_memory;

    if (is_constructor) {
        err =  JS_smprintf("The choice of Java constructor for class %s with "
                           "JavaScript argument types %s is ambiguous.\n",
                           class_descriptor->name,
                           js_arg_string);
        method_name = class_descriptor->name;
    } else {
        err =  JS_smprintf("The choice of %sJava method %s.%s matching "
                           "JavaScript argument types %s is ambiguous.\n",
                           is_static_method ? "static ": "",
                           class_descriptor->name, member_descriptor->name,
                           js_arg_string);
        method_name = member_descriptor->name;
    }
    if (!err)
        goto out_of_memory;

    tmp = JS_smprintf("%sCandidate methods are:\n", err);
    if (!tmp)
        goto out_of_memory;
    err = tmp;

    method_list_element = (MethodListElement*)JS_LIST_HEAD(ambiguous_methods);
    while ((MethodList*)method_list_element != ambiguous_methods) {
        method = method_list_element->method;
        method_str =
            jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature);
        if (!method_str)
            goto out_of_memory;
        tmp = JS_smprintf("%s   %s\n", err, method_str);
        free((char*)method_str);
        if (!tmp)
            goto out_of_memory;
        err = tmp;

        method_list_element = (MethodListElement*)method_list_element->linkage.next;
    }
    
    JS_ReportError(cx, err);
    return;

out_of_memory:
    if (js_arg_string)
        free((char*)js_arg_string);
    if (err)
        free((char*)err);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void report_method_match_failure ( JSContext cx,
JavaMemberDescriptor member_descriptor,
JavaClassDescriptor class_descriptor,
JSBool  is_static_method,
uintN  argc,
jsval argv 
) [static]

Definition at line 818 of file jsj_method.c.

{
    const char *err, *js_arg_string, *tmp, *method_str, *method_name;
    JSBool is_constructor;
    JavaMethodSpec *method;

    err = NULL;
    is_constructor = (!strcmp(member_descriptor->name, "<init>"));

    js_arg_string = get_js_arg_types_as_string(cx, argc, argv);
    if (!js_arg_string)
        goto out_of_memory;

    if (is_constructor) {
        err =  JS_smprintf("There is no Java constructor for class %s that matches "
                           "JavaScript argument types %s.\n", class_descriptor->name,
                           js_arg_string);
        method_name = class_descriptor->name;
    } else {
        err =  JS_smprintf("There is no %sJava method %s.%s that matches "
                           "JavaScript argument types %s.\n",
                           is_static_method ? "static ": "",
                           class_descriptor->name, member_descriptor->name, js_arg_string);
        method_name = member_descriptor->name;
    }
    if (!err)
        goto out_of_memory;

    tmp = JS_smprintf("%sCandidate methods with the same name are:\n", err);
    if (!tmp)
        goto out_of_memory;
    err = tmp;

    method = member_descriptor->methods;
    while (method) {
        method_str =
            jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature);
        if (!method_str)
            goto out_of_memory;
        tmp = JS_smprintf("%s   %s\n", err, method_str);
        free((char*)method_str);
        if (!tmp)
            goto out_of_memory;
        err = tmp;

        method = method->next;
    }
    
    JS_ReportError(cx, err);
    return;

out_of_memory:
    if (js_arg_string)
        free((char*)js_arg_string);
    if (err)
        free((char*)err);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JavaMethodSpec* resolve_overloaded_method ( JSContext cx,
JNIEnv jEnv,
JavaMemberDescriptor member_descriptor,
JavaClassDescriptor class_descriptor,
JSBool  is_static_method,
uintN  argc,
jsval argv 
) [static]

Definition at line 1215 of file jsj_method.c.

{
    JSJTypePreference preference;
    JavaMethodSpec *method, *best_method_match;
    MethodList ambiguous_methods;
    MethodListElement *method_list_element, *next_element;

    /*
     * Determine the first Java method among the overloaded methods of the same name
     * that matches all the JS arguments.
     */
    for (method = member_descriptor->methods; method; method = method->next) {
        if (method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature))
            break;
    }

    /* Report an error if no method matched the JS arguments */
    if (!method) {
        report_method_match_failure(cx, member_descriptor, class_descriptor,
                                    is_static_method, argc, argv);
        return NULL;
    }

    /* Shortcut a common case */
    if (!method->next)
        return method;

    /*
     * Form a list of all methods that are neither more or less preferred than the
     * best matching method discovered so far.
     */
    JS_INIT_CLIST(&ambiguous_methods);

    best_method_match = method;

    /* See if there are any Java methods that are a better fit for the JS args */
    for (method = method->next; method; method = method->next) {
        if (method->signature.num_args != (int)argc)
            continue;
        preference = method_preferred(cx, jEnv, argv, &best_method_match->signature,
                                      &method->signature);
        if (preference == JSJPREF_SECOND_ARG) {
            best_method_match = method;
        } else  if (preference == JSJPREF_AMBIGUOUS) {
            /* Add this method to the list of ambiguous methods */
            method_list_element =
                (MethodListElement*)JS_malloc(cx, sizeof(MethodListElement));
            if (!method_list_element)
                goto error;
            method_list_element->method = method;
            JS_APPEND_LINK(&method_list_element->linkage, &ambiguous_methods);
        }
    }
    
    /*
     * Ensure that best_method_match is preferred to all methods on the
     * ambiguous_methods list.
     */
    
    for (method_list_element = (MethodListElement*)JS_LIST_HEAD(&ambiguous_methods);
        (MethodList*)method_list_element != &ambiguous_methods;
         method_list_element = next_element) {
        next_element = (MethodListElement*)method_list_element->linkage.next;
        method = method_list_element->method;
        preference = method_preferred(cx, jEnv, argv, &best_method_match->signature,
                                      &method->signature);
        if (preference != JSJPREF_FIRST_ARG)
            continue;
        JS_REMOVE_LINK(&method_list_element->linkage);
        JS_free(cx, method_list_element);
    }
    
    /*
     * The chosen method must be maximally preferred, i.e. there can be no other
     * method that is just as preferred.
     */
    if (!JS_CLIST_IS_EMPTY(&ambiguous_methods)) {
        /* Add the best_method_match to the list of ambiguous methods */
       method_list_element =
           (MethodListElement*)JS_malloc(cx, sizeof(MethodListElement));
       if (!method_list_element)
           goto error;
       method_list_element->method = best_method_match;
       JS_APPEND_LINK(&method_list_element->linkage, &ambiguous_methods);

       /* Report the problem */
        report_ambiguous_method_match(cx, member_descriptor, class_descriptor,
                                      &ambiguous_methods, is_static_method, argc, argv);
        goto error;
    }

    return best_method_match;

error:
    /* Delete the storage for the ambiguous_method list */
    while (!JS_CLIST_IS_EMPTY(&ambiguous_methods)) {
        method_list_element = (MethodListElement*)JS_LIST_HEAD(&ambiguous_methods);
        JS_REMOVE_LINK(&method_list_element->linkage);
        JS_free(cx, method_list_element);
    }

    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static JSBool static_method_wrapper ( JSContext cx,
JSJavaThreadState jsj_env,
JavaClassDescriptor class_descriptor,
jsid  id,
uintN  argc,
jsval argv,
jsval vp 
) [static]

Definition at line 1717 of file jsj_method.c.

{
    JNIEnv *jEnv;
    JavaMemberDescriptor *member_descriptor;

    jEnv = jsj_env->jEnv;
    member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
    
    /* Is it a static method that is not a constructor ? */
    if (member_descriptor && strcmp(member_descriptor->name, "<init>")) {
        return invoke_overloaded_java_method(cx, jsj_env, member_descriptor, JS_TRUE, 
                                             class_descriptor->java_class,
                                             class_descriptor, argc, argv, vp);
    }

    JS_ASSERT(member_descriptor);
    if (!member_descriptor)
        return JS_FALSE;
    
    /* Must be an explicitly resolved overloaded constructor */
    return java_constructor_wrapper(cx, jsj_env, member_descriptor,
                                    class_descriptor, argc, argv, vp);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

Initial value:
 {


    {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,  1,  1}, 
    { 1, 99, 99, 99, 99, 99, 99, 99, 99, 99,  2, 99, 99, 99,  3,  4}, 
    {99,  7,  8,  6,  5,  4,  3,  1, 99, 99, 99, 99,  2, 99, 11,  9}, 
    {99,  3,  4,  4,  4,  4,  4,  4, 99, 99, 99, 99, 99, 99,  2,  1}, 
    {99, 99, 99, 99, 99, 99, 99, 99,  1,  1,  1,  1,  1,  1,  1,  1}, 
    {99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,  1, 99,  2,  3,  4}, 
    {99,  7,  8,  6,  5,  4,  3,  2,  0,  0,  0,  0,  0,  0,  0,  1}, 
    {99, 99, 99, 99, 99, 99, 99, 99,  0,  0, 99, 99, 99, 99,  0,  1}, 
    {99, 99, 99, 99, 99, 99, 99, 99,  2, 99, 99, 99, 99,  1,  3,  4}, 
    {99,  9, 10,  8,  7,  6,  5,  4, 99, 99, 99, 99, 99,  1,  2,  3}  
}

Definition at line 997 of file jsj_method.c.