📄 jsj_javapackage.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 the JavaPackage class. * * A JavaPackage is JavaScript's representation of a Java package. The * JavaPackage object contains only a string, which is the path to the package, * e.g. "java/lang". The JS properties of a JavaPackage are either nested packages * or a JavaClass object, which represents the path to a Java class. * * Note that there is no equivalent to a JavaPackage object in Java. Example: * 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 java.lang * object in Java that exists at run time. * */#include <stdlib.h>#include <string.h>#include "jsj_private.h" /* LiveConnect internals */#include "jsjava.h"JSClass JavaPackage_class; /* Forward declaration *//* * The native part of a JavaPackage object. It gets stored in the object's * private slot. */typedef struct { const char * path; /* e.g. "java/lang" or NULL if top level package */ int flags; /* e.g. PKG_SYSTEM, PKG_CLASS */} JavaPackage_Private;static JSObject *define_JavaPackage(JSContext *cx, JSObject *parent_obj, const char *obj_name, const char *path, int flags, int access){ JSObject *package_obj; JavaPackage_Private *package; package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0, JSPROP_PERMANENT | access); if (!package_obj) return NULL; /* Attach private, native data to the JS object */ package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private)); JS_SetPrivate(cx, package_obj, (void *)package); if (path) package->path = JS_strdup(cx, path); else package->path = ""; package->flags = flags; /* Check for OOM */ if (!package->path) { JS_DeleteProperty(cx, parent_obj, obj_name); JS_free(cx, package); return NULL; } return package_obj;}/* JavaPackage uses standard JS getProperty *//* * Don't allow user-defined properties to be set on Java package objects, e.g. * it is illegal to write "java.lang.myProperty = 4". We probably could relax * this restriction, but it's potentially confusing and not clearly useful. */JS_STATIC_DLL_CALLBACK(JSBool)JavaPackage_setProperty(JSContext *cx, JSObject *obj, jsval slot, jsval *vp){ JavaPackage_Private *package = JS_GetPrivate(cx, obj); if (!package) { JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_BAD_ADD_TO_PACKAGE); return JS_FALSE; } JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_DONT_ADD_TO_PACKAGE); return JS_FALSE;}static JSBool quiet_resolve_failure;/* * Resolve a component name to be either the name of a class or a package. */JS_STATIC_DLL_CALLBACK(JSBool)JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id){ JavaPackage_Private *package; JSBool ok = JS_TRUE; jclass jclazz; char *subPath, *newPath; const char *path; JNIEnv *jEnv; JSJavaThreadState *jsj_env; /* Painful hack for pre_define_java_packages() */ if (quiet_resolve_failure) return JS_FALSE; package = (JavaPackage_Private *)JS_GetPrivate(cx, obj); if (!package) return JS_TRUE; if (!JSVAL_IS_STRING(id)) return JS_TRUE; subPath = JS_GetStringBytes(JSVAL_TO_STRING(id)); /* * There will be an attempt to invoke the toString() method when producing * the string representation of a JavaPackage. When this occurs, avoid * creating a bogus toString package. (This means that no one can ever * create a package with the simple name "toString", but we'll live with * that limitation.) */ if (!strcmp(subPath, "toString")) return JS_FALSE; path = package->path; newPath = JS_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath); if (!newPath) { JS_ReportOutOfMemory(cx); return JS_FALSE; } jsj_env = jsj_EnterJava(cx, &jEnv); if (!jEnv) { ok = JS_FALSE; goto out; } /* Unfortunately, Java provides no way to find out whether a particular name is a package or not. The only way to tell is to try to load the name as a class file and, if that fails, assume it's a package. This makes things work as expected for the most part, but it has three noticeable problems that keep coming up: - You can refer to a package like java.lang.i.buried.paul without generating a complaint. Of course, you'll never be able to refer to any classes through it. - An annoying consequence of the above is that misspelling a class name results in a cryptic error about packages. - In a browser context, i.e. where applets are involved, figuring out whether something is a class may require looking for it over the net using the current classloader. This means that the first time you refer to java.lang.System in a js context, there will be an attempt to search for [[DOCBASE]]/java.class on the server. A solution is to explicitly tell jsjava the names of all the (local) packages on the CLASSPATH. (Not implemented yet.) */ jclazz = (*jEnv)->FindClass(jEnv, newPath); if (jclazz) { JSObject *newClass; newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz); (*jEnv)->DeleteLocalRef(jEnv, jclazz); if (!newClass) { ok = JS_FALSE; goto out; } } else { /* We assume that any failed attempt to load a class is because it doesn't exist. If we wanted to do a better job, we would check the exception type and make sure that it's NoClassDefFoundError */ (*jEnv)->ExceptionClear(jEnv); /* * If there's no class of the given name, then we must be referring to * a package. However, don't allow bogus sub-packages of pre-defined * system packages to be created. */ if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) { JavaPackage_Private *current_package; current_package = JS_GetPrivate(cx, obj); if (current_package->flags & PKG_SYSTEM) { char *msg, *cp; msg = JS_strdup(cx, newPath); /* Check for OOM */ if (msg) { /* Convert package of form "java/lang" to "java.lang" */ for (cp = msg; *cp != '\0'; cp++) if (*cp == '/') *cp = '.'; JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, JSJMSG_MISSING_PACKAGE, msg); free((char*)msg); } ok = JS_FALSE; goto out; } } if (!define_JavaPackage(cx, obj, subPath, newPath, 0, JSPROP_READONLY)) { ok = JS_FALSE; goto out; } #ifdef DEBUG /* printf("JavaPackage \'%s\' created\n", newPath); */#endif } out: free(newPath); jsj_ExitJava(jsj_env); return ok;}JS_STATIC_DLL_CALLBACK(JSBool)JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp){ JSString *str; char *name, *cp; JavaPackage_Private *package = JS_GetPrivate(cx, obj); if (!package) { fprintf(stderr, "JavaPackage_resolve: no private data!\n"); return JS_FALSE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -