/** * Return a List of SA Fields for all the java fields in this class, including all inherited * fields. This includes hidden fields. Thus the returned list can contain fields with the same * name. Return an empty list if there are no fields. Only designed for use in a debugging system. */ public List getAllFields() { // Contains a Field for each field in this class, including immediate // fields and inherited fields. List allFields = getImmediateFields(); // transitiveInterfaces contains all interfaces implemented // by this class and its superclass chain with no duplicates. ObjArray interfaces = getTransitiveInterfaces(); int n = (int) interfaces.getLength(); for (int i = 0; i < n; i++) { InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i); if (Assert.ASSERTS_ENABLED) { Assert.that(intf1.isInterface(), "just checking type"); } allFields.addAll(intf1.getImmediateFields()); } // Get all fields in the superclass, recursively. But, don't // include fields in interfaces implemented by superclasses; // we already have all those. if (!isInterface()) { InstanceKlass supr; if ((supr = (InstanceKlass) getSuper()) != null) { allFields.addAll(supr.getImmediateFields()); } } return allFields; }
private static int linearSearch(ObjArray methods, Symbol name, Symbol signature) { int len = (int) methods.getLength(); for (int index = 0; index < len; index++) { Method m = (Method) methods.getObjAt(index); if (m.getSignature().equals(signature) && m.getName().equals(name)) { return index; } } return -1; }
public boolean implementsInterface(Klass k) { if (Assert.ASSERTS_ENABLED) { Assert.that(k.isInterface(), "should not reach here"); } ObjArray interfaces = getTransitiveInterfaces(); final int len = (int) interfaces.getLength(); for (int i = 0; i < len; i++) { if (interfaces.getObjAt(i).equals(k)) return true; } return false; }
/** * Return a List containing an SA InstanceKlass for each interface named in this class's * 'implements' clause. */ public List getDirectImplementedInterfaces() { // Contains an InstanceKlass for each interface in this classes // 'implements' clause. ObjArray interfaces = getLocalInterfaces(); int length = (int) interfaces.getLength(); List directImplementedInterfaces = new ArrayList(length); for (int index = 0; index < length; index++) { directImplementedInterfaces.add(interfaces.getObjAt(index)); } return directImplementedInterfaces; }
private static Method findMethod(ObjArray methods, Symbol name, Symbol signature) { int len = (int) methods.getLength(); // methods are sorted, so do binary search int l = 0; int h = len - 1; while (l <= h) { int mid = (l + h) >> 1; Method m = (Method) methods.getObjAt(mid); int res = m.getName().fastCompare(name); if (res == 0) { // found matching name; do linear search to find matching signature // first, quick check for common case if (m.getSignature().equals(signature)) return m; // search downwards through overloaded methods int i; for (i = mid - 1; i >= l; i--) { Method m1 = (Method) methods.getObjAt(i); if (!m1.getName().equals(name)) break; if (m1.getSignature().equals(signature)) return m1; } // search upwards for (i = mid + 1; i <= h; i++) { Method m1 = (Method) methods.getObjAt(i); if (!m1.getName().equals(name)) break; if (m1.getSignature().equals(signature)) return m1; } // not found if (Assert.ASSERTS_ENABLED) { int index = linearSearch(methods, name, signature); if (index != -1) { throw new DebuggerException("binary search bug: should have found entry " + index); } } return null; } else if (res < 0) { l = mid + 1; } else { h = mid - 1; } } if (Assert.ASSERTS_ENABLED) { int index = linearSearch(methods, name, signature); if (index != -1) { throw new DebuggerException("binary search bug: should have found entry " + index); } } return null; }
/** * Return a List of SA Methods declared directly in this class/interface. Return an empty list if * there are none, or if this isn't a class/ interface. */ public List getImmediateMethods() { // Contains a Method for each method declared in this class/interface // not including inherited methods. ObjArray methods = getMethods(); int length = (int) methods.getLength(); Object[] tmp = new Object[length]; TypeArray methodOrdering = getMethodOrdering(); if (methodOrdering.getLength() != length) { // no ordering info present for (int index = 0; index < length; index++) { tmp[index] = methods.getObjAt(index); } } else { for (int index = 0; index < length; index++) { int originalIndex = getMethodOrdering().getIntAt(index); tmp[originalIndex] = methods.getObjAt(index); } } return Arrays.asList(tmp); }
/** Find field in direct superinterfaces. */ public Field findInterfaceField(Symbol name, Symbol sig) { ObjArray interfaces = getLocalInterfaces(); int n = (int) interfaces.getLength(); for (int i = 0; i < n; i++) { InstanceKlass intf1 = (InstanceKlass) interfaces.getObjAt(i); if (Assert.ASSERTS_ENABLED) { Assert.that(intf1.isInterface(), "just checking type"); } // search for field in current interface Field f = intf1.findLocalField(name, sig); if (f != null) { if (Assert.ASSERTS_ENABLED) { Assert.that(f.getAccessFlagsObj().isStatic(), "interface field must be static"); } return f; } // search for field in direct superinterfaces f = intf1.findInterfaceField(name, sig); if (f != null) return f; } // otherwise field lookup fails return null; }
private void reflect(Scriptable scope, boolean includeProtected) { // We reflect methods first, because we want overloaded field/method // names to be allocated to the NativeJavaMethod before the field // gets in the way. Method[] methods = discoverAccessibleMethods(cl, includeProtected, includePrivate); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; int mods = method.getModifiers(); boolean isStatic = Modifier.isStatic(mods); Map<String, Object> ht = isStatic ? staticMembers : members; String name = method.getName(); Object value = ht.get(name); if (value == null) { ht.put(name, method); } else { ObjArray overloadedMethods; if (value instanceof ObjArray) { overloadedMethods = (ObjArray) value; } else { if (!(value instanceof Method)) Kit.codeBug(); // value should be instance of Method as at this stage // staticMembers and members can only contain methods overloadedMethods = new ObjArray(); overloadedMethods.add(value); ht.put(name, overloadedMethods); } overloadedMethods.add(method); } } // replace Method instances by wrapped NativeJavaMethod objects // first in staticMembers and then in members for (int tableCursor = 0; tableCursor != 2; ++tableCursor) { boolean isStatic = (tableCursor == 0); Map<String, Object> ht = isStatic ? staticMembers : members; for (String name : ht.keySet()) { MemberBox[] methodBoxes; Object value = ht.get(name); 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 = getAccessibleFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; String name = field.getName(); int mods = field.getModifiers(); if (!includePrivate && !Modifier.isPublic(mods)) { continue; } try { boolean isStatic = Modifier.isStatic(mods); Map<String, Object> ht = isStatic ? staticMembers : members; 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); Map<String, FieldAndMethods> fmht = isStatic ? staticFieldAndMethods : fieldAndMethods; if (fmht == null) { fmht = new HashMap<String, FieldAndMethods>(); 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(); } } catch (SecurityException e) { // skip this field Context.reportWarning( "Could not access field " + name + " of class " + cl.getName() + " due to lack of privileges."); } } // Create bean properties 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); Map<String, Object> ht = isStatic ? staticMembers : members; Map<String, BeanProperty> toAdd = new HashMap<String, BeanProperty>(); // Now, For each member, make "bean" properties. for (String name : ht.keySet()) { // Is this a getter? boolean memberIsGetMethod = name.startsWith("get"); boolean memberIsSetMethod = name.startsWith("set"); boolean memberIsIsMethod = name.startsWith("is"); if (memberIsGetMethod || memberIsIsMethod || memberIsSetMethod) { // Double check name component. String nameComponent = name.substring(memberIsIsMethod ? 2 : 3); 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) || toAdd.containsKey(beanPropertyName)) { continue; } // Find the getter method, or if there is none, the is- // method. MemberBox getter = null; getter = findGetter(isStatic, ht, "get", nameComponent); // If there was no valid getter, check for an is- method. if (getter == null) { getter = findGetter(isStatic, ht, "is", nameComponent); } // setter MemberBox setter = null; NativeJavaMethod setters = null; String setterName = "set".concat(nameComponent); if (ht.containsKey(setterName)) { // Is this value a method? Object member = ht.get(setterName); if (member instanceof NativeJavaMethod) { NativeJavaMethod njmSet = (NativeJavaMethod) member; if (getter != null) { // We have a getter. Now, do we have a matching // setter? Class<?> type = getter.method().getReturnType(); setter = extractSetMethod(type, njmSet.methods, isStatic); } else { // No getter, find any set method setter = extractSetMethod(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 (String key : toAdd.keySet()) { Object value = toAdd.get(key); ht.put(key, value); } } // Reflect constructors Constructor<?>[] constructors = getAccessibleConstructors(); ctors = new MemberBox[constructors.length]; for (int i = 0; i != constructors.length; ++i) { ctors[i] = new MemberBox(constructors[i]); } }