Beispiel #1
0
  private Constructor<?>[] getAccessibleConstructors() {
    // The JVM currently doesn't allow changing access on java.lang.Class
    // constructors, so don't try
    if (includePrivate && cl != ScriptRuntime.ClassClass) {
      try {
        Constructor<?>[] cons = cl.getDeclaredConstructors();
        Constructor.setAccessible(cons, true);

        return cons;
      } catch (SecurityException e) {
        // Fall through to !includePrivate case
        Context.reportWarning(
            "Could not access constructor "
                + " of class "
                + cl.getName()
                + " due to lack of privileges.");
      }
    }
    return cl.getConstructors();
  }
Beispiel #2
0
  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]);
    }
  }
Beispiel #3
0
  private static void discoverAccessibleMethods(
      Class<?> clazz,
      Map<MethodSignature, Method> map,
      boolean includeProtected,
      boolean includePrivate) {
    if (Modifier.isPublic(clazz.getModifiers()) || includePrivate) {
      try {
        if (includeProtected || includePrivate) {
          while (clazz != null) {
            try {
              Method[] methods = clazz.getDeclaredMethods();
              for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                int mods = method.getModifiers();

                if (Modifier.isPublic(mods) || Modifier.isProtected(mods) || includePrivate) {
                  if (includePrivate) method.setAccessible(true);
                  map.put(new MethodSignature(method), method);
                }
              }
              clazz = clazz.getSuperclass();
            } catch (SecurityException e) {
              // Some security settings (i.e., applets) disallow
              // access to Class.getDeclaredMethods. Fall back to
              // Class.getMethods.
              Method[] methods = clazz.getMethods();
              for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                MethodSignature sig = new MethodSignature(method);
                if (map.get(sig) == null) map.put(sig, method);
              }
              break; // getMethods gets superclass methods, no
              // need to loop any more
            }
          }
        } else {
          Method[] methods = clazz.getMethods();
          for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            MethodSignature sig = new MethodSignature(method);
            map.put(sig, method);
          }
        }
        return;
      } catch (SecurityException e) {
        Context.reportWarning(
            "Could not discover accessible methods of class "
                + clazz.getName()
                + " due to lack of privileges, "
                + "attemping superclasses/interfaces.");
        // Fall through and attempt to discover superclass/interface
        // methods
      }
    }

    Class<?>[] interfaces = clazz.getInterfaces();
    for (int i = 0; i < interfaces.length; i++) {
      discoverAccessibleMethods(interfaces[i], map, includeProtected, includePrivate);
    }
    Class<?> superclass = clazz.getSuperclass();
    if (superclass != null) {
      discoverAccessibleMethods(superclass, map, includeProtected, includePrivate);
    }
  }