jsj_utils.c

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

C
510
字号
/* -*- 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 low-level utility code.
 *
 */

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

#include "jsj_private.h"        /* LiveConnect internals */
#include "jsjava.h"             /* External LiveConnect API */


/*
 * This is a hash-table utility routine that computes the hash code of a Java
 * object by calling java.lang.System.identityHashCode()
 */
JSJHashNumber JS_DLL_CALLBACK
jsj_HashJavaObject(const void *key, void* env)
{
    JSHashNumber hash_code;
    jobject java_obj;
    JNIEnv *jEnv;

    java_obj = (jobject)key;
    jEnv = (JNIEnv*) env;
    JS_ASSERT(!(*jEnv)->ExceptionOccurred(jEnv));
    hash_code = (*jEnv)->CallStaticIntMethod(jEnv, jlSystem,
                                             jlSystem_identityHashCode, java_obj);

#ifdef DEBUG
    if ((*jEnv)->ExceptionOccurred(jEnv)) {
        (*jEnv)->ExceptionDescribe(jEnv);
        JS_ASSERT(0);
    }
#endif

    return hash_code;
}

/* 
 * This is a hash-table utility routine for comparing two Java objects.
 * It's not possible to use the == operator to directly compare two jobject's,
 * since they're opaque references and aren't guaranteed to be simple pointers
 * or handles (though they may be in some JVM implementations).  Instead,
 * use the JNI routine for comparing the two objects.
 */
intN JS_DLL_CALLBACK
jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg)
{
    jobject java_obj1, java_obj2;
    JNIEnv *jEnv;

    jEnv = (JNIEnv*)arg;
    java_obj1 = (jobject)v1;
    java_obj2 = (jobject)v2;

    if (java_obj1 == java_obj2)
        return 1;
    if (jEnv)
        return (*jEnv)->IsSameObject(jEnv, java_obj1, java_obj2);
    return 0;
}

/*
 * Return a UTF8, null-terminated encoding of a Java string.  The string must
 * be free'ed by the caller.
 *
 * If an error occurs, returns NULL and calls the JS error reporter.
 */
const char *
jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr)
{
    const char *str, *retval;

    str = (*jEnv)->GetStringUTFChars(jEnv, jstr, 0);
    if (!str) {
        jsj_UnexpectedJavaError(cx, jEnv, "Can't get UTF8 characters from "
                                          "Java string");
        return NULL;
    }
    retval = JS_strdup(cx, str);
    (*jEnv)->ReleaseStringUTFChars(jEnv, jstr, str);
    return retval;
}

JSBool
JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp)
{
    const jschar *ucs2;
    JSString *jsstr;
    jsize ucs2_len;
    jsval val;
    
    ucs2 = (*jEnv)->GetStringChars(jEnv, jstr, 0);
    if (!ucs2) {
        jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain Unicode characters"
                                "from Java string");
        return JS_FALSE;
    }
    
    ucs2_len = (*jEnv)->GetStringLength(jEnv, jstr);
    jsstr = JS_InternUCStringN(cx, ucs2, ucs2_len);
    (*jEnv)->ReleaseStringChars(jEnv, jstr, ucs2);
    if (!jsstr)
        return JS_FALSE;

    val = STRING_TO_JSVAL(jsstr);
    JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp);
    return JS_TRUE;
}

/*
 * Return, as a C string, the error message associated with a Java exception
 * that occurred as a result of a JNI call, preceded by the class name of
 * the exception.  As a special case, if the class of the exception is
 * netscape.javascript.JSException, the exception class name is omitted.
 *
 * NULL is returned if no Java exception is pending.  The caller is
 * responsible for free'ing the returned string.  On exit, the Java exception
 * is *not* cleared.
 */
const char *
jsj_GetJavaErrorMessage(JNIEnv *jEnv)
{
    const char *java_error_msg;
    char *error_msg = NULL;
    jthrowable exception;
    jstring java_exception_jstring;

    exception = (*jEnv)->ExceptionOccurred(jEnv);
    if (exception && jlThrowable_toString) {
        java_exception_jstring =
            (*jEnv)->CallObjectMethod(jEnv, exception, jlThrowable_toString);
        if (!java_exception_jstring)
            goto done;
        java_error_msg = (*jEnv)->GetStringUTFChars(jEnv, java_exception_jstring, NULL);
        if (java_error_msg) {
            error_msg = strdup((char*)java_error_msg);
            (*jEnv)->ReleaseStringUTFChars(jEnv, java_exception_jstring, java_error_msg);
        }
        (*jEnv)->DeleteLocalRef(jEnv, java_exception_jstring);

#ifdef DEBUG
        /* (*jEnv)->ExceptionDescribe(jEnv); */
#endif
    }
done:
    if (exception)
        (*jEnv)->DeleteLocalRef(jEnv, exception);
    return error_msg;
}    

/*
 * Return, as a C string, the JVM stack trace associated with a Java
 * exception, as would be printed by java.lang.Throwable.printStackTrace().
 * The caller is responsible for free'ing the returned string.
 *
 * Returns NULL if an error occurs.
 */
static const char *
get_java_stack_trace(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception)
{
    const char *backtrace;
    jstring backtrace_jstr;

    backtrace = NULL;
    if (java_exception && njJSUtil_getStackTrace) {
        backtrace_jstr = (*jEnv)->CallStaticObjectMethod(jEnv, njJSUtil,
                                                         njJSUtil_getStackTrace,
                                                         java_exception);
        if (!backtrace_jstr) {
            jsj_UnexpectedJavaError(cx, jEnv, "Unable to get exception stack trace");
            return NULL;
        }
        backtrace = jsj_DupJavaStringUTF(cx, jEnv, backtrace_jstr);
        (*jEnv)->DeleteLocalRef(jEnv, backtrace_jstr);
    }
    return backtrace;
} 

/* Full Java backtrace when Java exceptions reported to JavaScript */
#define REPORT_JAVA_EXCEPTION_STACK_TRACE

/*
 * This is a wrapper around JS_ReportError(), useful when an error condition
 * is the result of a JVM failure or exception condition.  It appends the
 * message associated with the pending Java exception to the passed in
 * printf-style format string and arguments.
 */
static void
vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap)
{
    jobject java_obj;
    jclass java_class;
    JavaClassDescriptor *class_descriptor;
    jthrowable java_exception;
    JSType wrapped_exception_type;
    jsval js_exception;
       
    java_obj = NULL;
    class_descriptor = NULL;

    /* Get the exception out of the java environment. */
    java_exception = (*jEnv)->ExceptionOccurred(jEnv);
    if (!java_exception) {
        JSString *err_jsstr;

⌨️ 快捷键说明

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