📄 javamembers.java
字号:
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * 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 Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Norris Boyd * Cameron McCormack * Frank Mitchell * Mike Shaver * Kurt Westerfeld * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */package org.mozilla.javascript;import java.lang.reflect.*;import java.util.*;/** * * @author Mike Shaver * @author Norris Boyd * @see NativeJavaObject * @see NativeJavaClass */class JavaMembers{ JavaMembers(Scriptable scope, Class cl) { this(scope, cl, false); } JavaMembers(Scriptable scope, Class cl, boolean includeProtected) { try { Context cx = ContextFactory.getGlobal().enterContext(); ClassShutter shutter = cx.getClassShutter(); if (shutter != null && !shutter.visibleToScripts(cl.getName())) { throw Context.reportRuntimeError1("msg.access.prohibited", cl.getName()); } this.includePrivate = cx.hasFeature( Context.FEATURE_ENHANCED_JAVA_ACCESS); this.members = new Hashtable(23); this.staticMembers = new Hashtable(7); this.cl = cl; reflect(scope, includeProtected); } finally { Context.exit(); } } boolean has(String name, boolean isStatic) { Hashtable ht = isStatic ? staticMembers : members; Object obj = ht.get(name); if (obj != null) { return true; } return findExplicitFunction(name, isStatic) != null; } Object get(Scriptable scope, String name, Object javaObject, boolean isStatic) { Hashtable ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (!isStatic && member == null) { // Try to get static member from instance (LC3) member = staticMembers.get(name); } if (member == null) { member = this.getExplicitFunction(scope, name, javaObject, isStatic); if (member == null) return Scriptable.NOT_FOUND; } if (member instanceof Scriptable) { return member; } Context cx = Context.getContext(); Object rval; Class type; try { if (member instanceof BeanProperty) { BeanProperty bp = (BeanProperty) member; if (bp.getter == null) return Scriptable.NOT_FOUND; rval = bp.getter.invoke(javaObject, Context.emptyArgs); type = bp.getter.method().getReturnType(); } else { Field field = (Field) member; rval = field.get(isStatic ? null : javaObject); type = field.getType(); } } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } // Need to wrap the object before we return it. scope = ScriptableObject.getTopLevelScope(scope); return cx.getWrapFactory().wrap(cx, scope, rval, type); } void put(Scriptable scope, String name, Object javaObject, Object value, boolean isStatic) { Hashtable ht = isStatic ? staticMembers : members; Object member = ht.get(name); if (!isStatic && member == null) { // Try to get static member from instance (LC3) member = staticMembers.get(name); } if (member == null) throw reportMemberNotFound(name); if (member instanceof FieldAndMethods) { FieldAndMethods fam = (FieldAndMethods) ht.get(name); member = fam.field; } // Is this a bean property "set"? if (member instanceof BeanProperty) { BeanProperty bp = (BeanProperty)member; if (bp.setter == null) { throw reportMemberNotFound(name); } // If there's only one setter or if the value is null, use the // main setter. Otherwise, let the NativeJavaMethod decide which // setter to use: if (bp.setters == null || value == null) { Class setType = bp.setter.argTypes[0]; Object[] args = { Context.jsToJava(value, setType) }; try { bp.setter.invoke(javaObject, args); } catch (Exception ex) { throw Context.throwAsScriptRuntimeEx(ex); } } else { Object[] args = { value }; bp.setters.call(Context.getContext(), ScriptableObject.getTopLevelScope(scope), scope, args); } } else { if (!(member instanceof Field)) { String str = (member == null) ? "msg.java.internal.private" : "msg.java.method.assign"; throw Context.reportRuntimeError1(str, name); } Field field = (Field)member; Object javaValue = Context.jsToJava(value, field.getType()); try { field.set(javaObject, javaValue); } catch (IllegalAccessException accessEx) { if ((field.getModifiers() & Modifier.FINAL) != 0) { // treat Java final the same as JavaScript [[READONLY]] return; } throw Context.throwAsScriptRuntimeEx(accessEx); } catch (IllegalArgumentException argEx) { throw Context.reportRuntimeError3( "msg.java.internal.field.type", value.getClass().getName(), field, javaObject.getClass().getName()); } } } Object[] getIds(boolean isStatic) { Hashtable ht = isStatic ? staticMembers : members; int len = ht.size(); Object[] result = new Object[len]; Enumeration keys = ht.keys(); for (int i=0; i < len; i++) result[i] = keys.nextElement(); return result; } static String javaSignature(Class type) { if (!type.isArray()) { return type.getName(); } else { int arrayDimension = 0; do { ++arrayDimension; type = type.getComponentType(); } while (type.isArray()); String name = type.getName(); String suffix = "[]"; if (arrayDimension == 1) { return name.concat(suffix); } else { int length = name.length() + arrayDimension * suffix.length(); StringBuffer sb = new StringBuffer(length); sb.append(name); while (arrayDimension != 0) { --arrayDimension; sb.append(suffix); } return sb.toString(); } } } static String liveConnectSignature(Class[] argTypes) { int N = argTypes.length; if (N == 0) { return "()"; } StringBuffer sb = new StringBuffer(); sb.append('('); for (int i = 0; i != N; ++i) { if (i != 0) { sb.append(','); } sb.append(javaSignature(argTypes[i])); } sb.append(')'); return sb.toString(); } private MemberBox findExplicitFunction(String name, boolean isStatic) { int sigStart = name.indexOf('('); if (sigStart < 0) { return null; } Hashtable ht = isStatic ? staticMembers : members; MemberBox[] methodsOrCtors = null; boolean isCtor = (isStatic && sigStart == 0); if (isCtor) { // Explicit request for an overloaded constructor methodsOrCtors = ctors; } else { // Explicit request for an overloaded method String trueName = name.substring(0,sigStart); Object obj = ht.get(trueName); if (!isStatic && obj == null) { // Try to get static member from instance (LC3) obj = staticMembers.get(trueName); } if (obj instanceof NativeJavaMethod) { NativeJavaMethod njm = (NativeJavaMethod)obj; methodsOrCtors = njm.methods; } } if (methodsOrCtors != null) { for (int i = 0; i < methodsOrCtors.length; i++) { Class[] type = methodsOrCtors[i].argTypes; String sig = liveConnectSignature(type); if (sigStart + sig.length() == name.length() && name.regionMatches(sigStart, sig, 0, sig.length())) { return methodsOrCtors[i]; } } } return null; } private Object getExplicitFunction(Scriptable scope, String name, Object javaObject, boolean isStatic) { Hashtable ht = isStatic ? staticMembers : members; Object member = null; MemberBox methodOrCtor = findExplicitFunction(name, isStatic); if (methodOrCtor != null) { Scriptable prototype = ScriptableObject.getFunctionPrototype(scope); if (methodOrCtor.isCtor()) { NativeJavaConstructor fun = new NativeJavaConstructor(methodOrCtor); fun.setPrototype(prototype); member = fun; ht.put(name, fun); } else { String trueName = methodOrCtor.getName(); member = ht.get(trueName);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -