jsj_javaclass.c

来自「一个基于alice开发的机器人」· C语言 代码 · 共 750 行 · 第 1/2 页

C
750
字号
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * ***** 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.
 *
 * ***** END LICENSE BLOCK ***** */

/* This file is part of the Java-vendor-neutral implementation of LiveConnect
 *
 * It contains the native code implementation of JS's JavaClass class.
 *
 * A JavaClass is JavaScript's representation of a Java class.
 * Its parent JS object is always a JavaPackage object.  A JavaClass is not an
 * exact reflection of Java's corresponding java.lang.Class object.  Rather,
 * the properties of a JavaClass are the static methods and properties of the
 * corresponding Java class.
 *
 * Note that there is no runtime equivalent to the JavaClass class in Java.
 * (Although there are instances of java.lang.String and there are static
 * methods of java.lang.String that can be invoked, there's no such thing as
 * a first-class object that can be referenced simply as "java.lang.String".)
 */

#include <stdlib.h>
#include <string.h>

#include "jsj_private.h"        /* LiveConnect internals */
#include "jscntxt.h"            /* for error reporting */

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
{
    char *name;
    JSString *str;

    JavaClassDescriptor *class_descriptor;
    
    class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor)
        return JS_FALSE;

    switch(type) {


    case JSTYPE_STRING:
        /* Convert '/' to '.' so that it looks like Java language syntax. */
        if (!class_descriptor->name)
            break;
        name = JS_smprintf("[JavaClass %s]", class_descriptor->name);
        if (!name) {
            JS_ReportOutOfMemory(cx);
            return JS_FALSE;
        }

        str = JS_NewString(cx, name, strlen(name));
        if (!str) {
            free(name);
            /* It's not necessary to call JS_ReportOutOfMemory(), as
               JS_NewString() will do so on failure. */
            return JS_FALSE;
        }

        *vp = STRING_TO_JSVAL(str);
        return JS_TRUE;

    default:
      break;
    }
    return JS_TRUE;
}

static JSBool
lookup_static_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj,
                           JavaClassDescriptor **class_descriptorp,
                           jsid id, JavaMemberDescriptor **memberp)
{
    jsval idval;
    JavaMemberDescriptor *member_descriptor;
    const char *member_name;
    JavaClassDescriptor *class_descriptor;

    class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor) {
        *class_descriptorp = NULL;
        *memberp = NULL;
        return JS_TRUE;
    }
    
    if (class_descriptorp)
        *class_descriptorp = class_descriptor;
    
    member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id);
    if (!member_descriptor) {
        JS_IdToValue(cx, id, &idval);
        if (!JSVAL_IS_STRING(idval)) {
            JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                                            JSJMSG_BAD_JCLASS_EXPR);
            return JS_FALSE;
        }

        member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
        
        /*
         * See if the property looks like the explicit resolution of an
         * overloaded method, e.g. "max(double,double)".
         */
        member_descriptor =
            jsj_ResolveExplicitMethod(cx, jEnv, class_descriptor, id, JS_TRUE);
        if (member_descriptor)
            goto done;

        /* Why do we have to do this ? */
        if (!strcmp(member_name, "prototype")) {
            *memberp = NULL;
            return JS_TRUE;
        }

        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                        JSJMSG_MISSING_NAME,
                       class_descriptor->name, member_name);
        return JS_FALSE;
    }

done:
    if (memberp)
        *memberp = member_descriptor;
    return JS_TRUE;
}

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
    jsval idval;
    jclass java_class;
    const char *member_name;
    JavaClassDescriptor *class_descriptor;
    JavaMemberDescriptor *member_descriptor;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;

    /* printf("In JavaClass_getProperty\n"); */
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }
    if (!member_descriptor) {
        *vp = JSVAL_VOID;
	jsj_ExitJava(jsj_env);
        return JS_TRUE;
    }

    java_class = class_descriptor->java_class;

    if (member_descriptor->field) {
        if (!member_descriptor->methods) {
            result = jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp);
	    jsj_ExitJava(jsj_env);
	    return result;
        } else {
            JS_ASSERT(0);
        }
    } else {
        JSFunction *function;
        
        /* TODO - eliminate JSFUN_BOUND_METHOD */
        if (member_descriptor->methods->is_alias) {
            /* If this is an explicit resolution of an overloaded method,
               use the fully-qualified method name as the name of the
               resulting JS function, i.e. "myMethod(int,long)" */
            JS_IdToValue(cx, id, &idval);
            member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
        } else {
            /* Either not explicit resolution of overloaded method or
               explicit resolution was unnecessary because method was
               not overloaded. */
            member_name = member_descriptor->name;
        }
        function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0,
                                  JSFUN_BOUND_METHOD, obj, member_name);
        if (!function) {
	    jsj_ExitJava(jsj_env);
            return JS_FALSE;
	}

        *vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function));
    }

    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{
    jclass java_class;
    const char *member_name;
    JavaClassDescriptor *class_descriptor;
    JavaMemberDescriptor *member_descriptor;
    jsval idval;
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;
    JSBool result;

    /* printf("In JavaClass_setProperty\n"); */

    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;
    
    if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) {
	jsj_ExitJava(jsj_env);
        return JS_FALSE;
    }

    /* Check for the case where there is a method with the given name, but no field
       with that name */
    if (!member_descriptor->field)
        goto no_such_field;

    /* Silently fail if field value is final (immutable), as required by ECMA spec */
    if (member_descriptor->field->modifiers & ACC_FINAL) {
	jsj_ExitJava(jsj_env);
        return JS_TRUE;
    }

    java_class = class_descriptor->java_class;
    result = jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp);
    jsj_ExitJava(jsj_env);
    return result;

no_such_field:
    JS_IdToValue(cx, id, &idval);
    member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval));
    JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                   JSJMSG_MISSING_STATIC,
                   member_name, class_descriptor->name);
    jsj_ExitJava(jsj_env);
    return JS_FALSE;
}

/*
 * Free the private native data associated with the JavaPackage object.
 */
JS_STATIC_DLL_CALLBACK(void)
JavaClass_finalize(JSContext *cx, JSObject *obj)
{
    JNIEnv *jEnv;
    JSJavaThreadState *jsj_env;

    JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj);
    if (!class_descriptor)
        return;
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return;

    /* printf("Finalizing %s\n", class_descriptor->name); */
    jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor);
    jsj_ExitJava(jsj_env);
}


JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id,
                         JSObject **objp, JSProperty **propp
#if defined JS_THREADSAFE && defined DEBUG
                            , const char *file, uintN line
#endif
                            )
{
    JNIEnv *jEnv;
    JSErrorReporter old_reporter;
    JSJavaThreadState *jsj_env;

    /* printf("In JavaClass_lookupProperty()\n"); */
    
    /* Get the Java per-thread environment pointer for this JSContext */
    jsj_env = jsj_EnterJava(cx, &jEnv);
    if (!jEnv)
        return JS_FALSE;

    old_reporter = JS_SetErrorReporter(cx, NULL);
    if (lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) {
        *objp = obj;
        *propp = (JSProperty*)1;
    } else {
        *objp = NULL;
        *propp = NULL;
    }

    JS_SetErrorReporter(cx, old_reporter);
    jsj_ExitJava(jsj_env);
    return JS_TRUE;
}

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
                         JSPropertyOp getter, JSPropertyOp setter,
                         uintN attrs, JSProperty **propp)
{
    JavaClassDescriptor *class_descriptor;
    
    class_descriptor = JS_GetPrivate(cx, obj);

    /* Check for prototype JavaClass object */
    if (!class_descriptor)
	return JS_TRUE;

    JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                         JSJMSG_JCLASS_PROP_DEFINE);
    return JS_FALSE;
}

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_getAttributes(JSContext *cx, JSObject *obj, jsid id,
                        JSProperty *prop, uintN *attrsp)
{
    /* We don't maintain JS property attributes for Java class members */
    *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE;
    return JS_FALSE;
}

JS_STATIC_DLL_CALLBACK(JSBool)
JavaClass_setAttributes(JSContext *cx, JSObject *obj, jsid id,
                        JSProperty *prop, uintN *attrsp)
{
    /* We don't maintain JS property attributes for Java class members */
    if (*attrsp != (JSPROP_PERMANENT|JSPROP_ENUMERATE)) {
        JS_ASSERT(0);
        return JS_FALSE;
    }

    /* Silently ignore all setAttribute attempts */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?