📄 jsj_javaclass.c
字号:
/* -*- 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 JSBoollookup_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){ 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 */ return JS_TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -