📄 javamembers.java
字号:
if (value instanceof Method) { methodBoxes = new MemberBox[1]; methodBoxes[0] = new MemberBox((Method)value); } else { ObjArray overloadedMethods = (ObjArray)value; int N = overloadedMethods.size(); if (N < 2) Kit.codeBug(); methodBoxes = new MemberBox[N]; for (int i = 0; i != N; ++i) { Method method = (Method)overloadedMethods.get(i); methodBoxes[i] = new MemberBox(method); } } NativeJavaMethod fun = new NativeJavaMethod(methodBoxes); if (scope != null) { ScriptRuntime.setFunctionProtoAndParent(fun, scope); } ht.put(name, fun); } } // Reflect fields. Field[] fields = cl.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; int mods = field.getModifiers(); if (!Modifier.isPublic(mods)) { continue; } boolean isStatic = Modifier.isStatic(mods); Hashtable ht = isStatic ? staticMembers : members; String name = field.getName(); Object member = ht.get(name); if (member == null) { ht.put(name, field); } else if (member instanceof NativeJavaMethod) { NativeJavaMethod method = (NativeJavaMethod) member; FieldAndMethods fam = new FieldAndMethods(scope, method.methods, field); Hashtable fmht = isStatic ? staticFieldAndMethods : fieldAndMethods; if (fmht == null) { fmht = new Hashtable(4); if (isStatic) { staticFieldAndMethods = fmht; } else { fieldAndMethods = fmht; } } fmht.put(name, fam); ht.put(name, fam); } else if (member instanceof Field) { Field oldField = (Field) member; // If this newly reflected field shadows an inherited field, // then replace it. Otherwise, since access to the field // would be ambiguous from Java, no field should be reflected. // For now, the first field found wins, unless another field // explicitly shadows it. if (oldField.getDeclaringClass(). isAssignableFrom(field.getDeclaringClass())) { ht.put(name, field); } } else { // "unknown member type" Kit.codeBug(); } } // Create bean propeties from corresponding get/set methods first for // static members and then for instance members for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { boolean isStatic = (tableCursor == 0); Hashtable ht = (isStatic) ? staticMembers : members; Hashtable toAdd = new Hashtable(); // Now, For each member, make "bean" properties. for (Enumeration e = ht.keys(); e.hasMoreElements(); ) { // Is this a getter? String name = (String) e.nextElement(); boolean memberIsGetMethod = name.startsWith("get"); boolean memberIsIsMethod = name.startsWith("is"); if (memberIsGetMethod || memberIsIsMethod) { // Double check name component. String nameComponent = name.substring(memberIsGetMethod ? 3 : 2); if (nameComponent.length() == 0) continue; // Make the bean property name. String beanPropertyName = nameComponent; char ch0 = nameComponent.charAt(0); if (Character.isUpperCase(ch0)) { if (nameComponent.length() == 1) { beanPropertyName = nameComponent.toLowerCase(); } else { char ch1 = nameComponent.charAt(1); if (!Character.isUpperCase(ch1)) { beanPropertyName = Character.toLowerCase(ch0) +nameComponent.substring(1); } } } // If we already have a member by this name, don't do this // property. if (ht.containsKey(beanPropertyName)) continue; // Get the method by this name. Object member = ht.get(name); if (!(member instanceof NativeJavaMethod)) continue; NativeJavaMethod njmGet = (NativeJavaMethod)member; MemberBox getter = extractGetMethod(njmGet.methods, isStatic); if (getter != null) { // We have a getter. Now, do we have a setter? NativeJavaMethod njmSet = null; MemberBox setter = null; NativeJavaMethod setters = null; String setterName = "set".concat(nameComponent); if (ht.containsKey(setterName)) { // Is this value a method? member = ht.get(setterName); if (member instanceof NativeJavaMethod) { njmSet = (NativeJavaMethod)member; Class type = getter.method().getReturnType(); setter = extractSetMethod(type, njmSet.methods, isStatic); if (njmSet.methods.length > 1) { setters = njmSet; } } } // Make the property. BeanProperty bp = new BeanProperty(getter, setter, setters); toAdd.put(beanPropertyName, bp); } } } // Add the new bean properties. for (Enumeration e = toAdd.keys(); e.hasMoreElements();) { Object key = e.nextElement(); Object value = toAdd.get(key); ht.put(key, value); } } // Reflect constructors Constructor[] constructors = cl.getConstructors(); ctors = new MemberBox[constructors.length]; for (int i = 0; i != constructors.length; ++i) { ctors[i] = new MemberBox(constructors[i]); } } private static MemberBox extractGetMethod(MemberBox[] methods, boolean isStatic) { // Inspect the list of all MemberBox for the only one having no // parameters for (int methodIdx = 0; methodIdx < methods.length; methodIdx++) { MemberBox method = methods[methodIdx]; // Does getter method have an empty parameter list with a return // value (eg. a getSomething() or isSomething())? if (method.argTypes.length == 0 && (!isStatic || method.isStatic())) { Class type = method.method().getReturnType(); if (type != Void.TYPE) { return method; } break; } } return null; } private static MemberBox extractSetMethod(Class type, MemberBox[] methods, boolean isStatic) { // // Note: it may be preferable to allow NativeJavaMethod.findFunction() // to find the appropriate setter; unfortunately, it requires an // instance of the target arg to determine that. // // Make two passes: one to find a method with direct type assignment, // and one to find a widening conversion. for (int pass = 1; pass <= 2; ++pass) { for (int i = 0; i < methods.length; ++i) { MemberBox method = methods[i]; if (!isStatic || method.isStatic()) { if (method.method().getReturnType() == Void.TYPE) { Class[] params = method.argTypes; if (params.length == 1) { if (pass == 1) { if (params[0] == type) { return method; } } else { if (pass != 2) Kit.codeBug(); if (params[0].isAssignableFrom(type)) { return method; } } } } } } } return null; } Hashtable getFieldAndMethodsObjects(Scriptable scope, Object javaObject, boolean isStatic) { Hashtable ht = isStatic ? staticFieldAndMethods : fieldAndMethods; if (ht == null) return null; int len = ht.size(); Hashtable result = new Hashtable(len); Enumeration e = ht.elements(); while (len-- > 0) { FieldAndMethods fam = (FieldAndMethods) e.nextElement(); FieldAndMethods famNew = new FieldAndMethods(scope, fam.methods, fam.field); famNew.javaObject = javaObject; result.put(fam.field.getName(), famNew); } return result; } static JavaMembers lookupClass(Scriptable scope, Class dynamicType, Class staticType) { JavaMembers members; ClassCache cache = ClassCache.get(scope); Hashtable ct = cache.classTable; Class cl = dynamicType; for (;;) { members = (JavaMembers)ct.get(cl); if (members != null) { return members; } try { members = new JavaMembers(cache.scope, cl); break; } catch (SecurityException e) { // Reflection may fail for objects that are in a restricted // access package (e.g. sun.*). If we get a security // exception, try again with the static type if it is interface. // Otherwise, try superclass if (staticType != null && staticType.isInterface()) { cl = staticType; staticType = null; // try staticType only once } else { Class parent = cl.getSuperclass(); if (parent == null) { if (cl.isInterface()) { // last resort after failed staticType interface parent = ScriptRuntime.ObjectClass; } else { throw e; } } cl = parent; } } } if (cache.isCachingEnabled()) ct.put(cl, members); return members; } RuntimeException reportMemberNotFound(String memberName) { return Context.reportRuntimeError2( "msg.java.member.not.found", cl.getName(), memberName); } private Class cl; private Hashtable members; private Hashtable fieldAndMethods; private Hashtable staticMembers; private Hashtable staticFieldAndMethods; MemberBox[] ctors;}class BeanProperty{ BeanProperty(MemberBox getter, MemberBox setter, NativeJavaMethod setters) { this.getter = getter; this.setter = setter; this.setters = setters; } MemberBox getter; MemberBox setter; NativeJavaMethod setters;}class FieldAndMethods extends NativeJavaMethod{ static final long serialVersionUID = -9222428244284796755L; FieldAndMethods(Scriptable scope, MemberBox[] methods, Field field) { super(methods); this.field = field; setParentScope(scope); setPrototype(ScriptableObject.getFunctionPrototype(scope)); } public Object getDefaultValue(Class hint) { if (hint == ScriptRuntime.FunctionClass) return this; Object rval; Class type; try { rval = field.get(javaObject); type = field.getType(); } catch (IllegalAccessException accEx) { throw Context.reportRuntimeError1( "msg.java.internal.private", field.getName()); } Context cx = Context.getContext(); rval = cx.getWrapFactory().wrap(cx, this, rval, type); if (rval instanceof Scriptable) { rval = ((Scriptable) rval).getDefaultValue(hint); } return rval; } Field field; Object javaObject;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -