Can execute a (parameterless) method via reflection reflection
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 04 Dec 2012 15:32:18 +0100
branchreflection
changeset 262683719ffcfe7
parent 261 5d1e20215d12
child 264 ed0c92c81ea4
Can execute a (parameterless) method via reflection
emul/src/main/java/java/lang/Class.java
emul/src/main/java/java/lang/reflect/Method.java
     1.1 --- a/emul/src/main/java/java/lang/Class.java	Tue Dec 04 14:49:01 2012 +0100
     1.2 +++ b/emul/src/main/java/java/lang/Class.java	Tue Dec 04 15:32:18 2012 +0100
     1.3 @@ -747,7 +747,11 @@
     1.4       */
     1.5      public Method getMethod(String name, Class<?>... parameterTypes)
     1.6          throws SecurityException {
     1.7 -        throw new SecurityException();
     1.8 +        Method m = Method.findMethod(this, name, parameterTypes);
     1.9 +        if (m == null) {
    1.10 +            throw new SecurityException(); // XXX: NoSuchMethodException
    1.11 +        }
    1.12 +        return m;
    1.13      }
    1.14  
    1.15      /**
     2.1 --- a/emul/src/main/java/java/lang/reflect/Method.java	Tue Dec 04 14:49:01 2012 +0100
     2.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java	Tue Dec 04 15:32:18 2012 +0100
     2.3 @@ -26,6 +26,7 @@
     2.4  package java.lang.reflect;
     2.5  
     2.6  import java.lang.annotation.Annotation;
     2.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
     2.8  
     2.9  /**
    2.10   * A {@code Method} provides information about, and access to, a single method
    2.11 @@ -50,28 +51,14 @@
    2.12  public final
    2.13      class Method extends AccessibleObject implements GenericDeclaration,
    2.14                                                       Member {
    2.15 -    private Class<?>            clazz;
    2.16 -    private int                 slot;
    2.17 -    // This is guaranteed to be interned by the VM in the 1.4
    2.18 -    // reflection implementation
    2.19 -    private String              name;
    2.20 -    private Class<?>            returnType;
    2.21 -    private Class<?>[]          parameterTypes;
    2.22 -    private Class<?>[]          exceptionTypes;
    2.23 -    private int                 modifiers;
    2.24 -    // Generics and annotations support
    2.25 -    private transient String              signature;
    2.26 -    private byte[]              annotations;
    2.27 -    private byte[]              parameterAnnotations;
    2.28 -    private byte[]              annotationDefault;
    2.29 -    // For sharing of MethodAccessors. This branching structure is
    2.30 -    // currently only two levels deep (i.e., one root Method and
    2.31 -    // potentially many Method objects pointing to it.)
    2.32 -    private Method              root;
    2.33 +    private final Class<?> clazz;
    2.34 +    private final String name;
    2.35 +    private final Object data;
    2.36 +    private int modifiers;
    2.37  
    2.38     // Generics infrastructure
    2.39  
    2.40 -    private String getGenericSignature() {return signature;}
    2.41 +    private String getGenericSignature() {return null;}
    2.42  
    2.43      /**
    2.44       * Package-private constructor used by ReflectAccess to enable
    2.45 @@ -79,28 +66,11 @@
    2.46       * package via sun.reflect.LangReflectAccess.
    2.47       */
    2.48      Method(Class<?> declaringClass,
    2.49 -           String name,
    2.50 -           Class<?>[] parameterTypes,
    2.51 -           Class<?> returnType,
    2.52 -           Class<?>[] checkedExceptions,
    2.53 -           int modifiers,
    2.54 -           int slot,
    2.55 -           String signature,
    2.56 -           byte[] annotations,
    2.57 -           byte[] parameterAnnotations,
    2.58 -           byte[] annotationDefault)
    2.59 +           String name, Object data)
    2.60      {
    2.61          this.clazz = declaringClass;
    2.62          this.name = name;
    2.63 -        this.parameterTypes = parameterTypes;
    2.64 -        this.returnType = returnType;
    2.65 -        this.exceptionTypes = checkedExceptions;
    2.66 -        this.modifiers = modifiers;
    2.67 -        this.slot = slot;
    2.68 -        this.signature = signature;
    2.69 -        this.annotations = annotations;
    2.70 -        this.parameterAnnotations = parameterAnnotations;
    2.71 -        this.annotationDefault = annotationDefault;
    2.72 +        this.data = data;
    2.73      }
    2.74  
    2.75      /**
    2.76 @@ -109,18 +79,7 @@
    2.77       * "root" field points to this Method.
    2.78       */
    2.79      Method copy() {
    2.80 -        // This routine enables sharing of MethodAccessor objects
    2.81 -        // among Method objects which refer to the same underlying
    2.82 -        // method in the VM. (All of this contortion is only necessary
    2.83 -        // because of the "accessibility" bit in AccessibleObject,
    2.84 -        // which implicitly requires that new java.lang.reflect
    2.85 -        // objects be fabricated for each reflective call on Class
    2.86 -        // objects.)
    2.87 -        Method res = new Method(clazz, name, parameterTypes, returnType,
    2.88 -                                exceptionTypes, modifiers, slot, signature,
    2.89 -                                annotations, parameterAnnotations, annotationDefault);
    2.90 -        res.root = this;
    2.91 -        return res;
    2.92 +        return this;
    2.93      }
    2.94  
    2.95      /**
    2.96 @@ -176,7 +135,7 @@
    2.97       * @return the return type for the method this object represents
    2.98       */
    2.99      public Class<?> getReturnType() {
   2.100 -        return returnType;
   2.101 +        throw new UnsupportedOperationException();
   2.102      }
   2.103  
   2.104      /**
   2.105 @@ -218,7 +177,8 @@
   2.106       * represents
   2.107       */
   2.108      public Class<?>[] getParameterTypes() {
   2.109 -        return (Class<?>[]) parameterTypes.clone();
   2.110 +        throw new UnsupportedOperationException();
   2.111 +        //return (Class<?>[]) parameterTypes.clone();
   2.112      }
   2.113  
   2.114      /**
   2.115 @@ -264,7 +224,8 @@
   2.116       * method this object represents
   2.117       */
   2.118      public Class<?>[] getExceptionTypes() {
   2.119 -        return (Class<?>[]) exceptionTypes.clone();
   2.120 +        throw new UnsupportedOperationException();
   2.121 +        //return (Class<?>[]) exceptionTypes.clone();
   2.122      }
   2.123  
   2.124      /**
   2.125 @@ -302,21 +263,7 @@
   2.126      public boolean equals(Object obj) {
   2.127          if (obj != null && obj instanceof Method) {
   2.128              Method other = (Method)obj;
   2.129 -            if ((getDeclaringClass() == other.getDeclaringClass())
   2.130 -                && (getName() == other.getName())) {
   2.131 -                if (!returnType.equals(other.getReturnType()))
   2.132 -                    return false;
   2.133 -                /* Avoid unnecessary cloning */
   2.134 -                Class<?>[] params1 = parameterTypes;
   2.135 -                Class<?>[] params2 = other.parameterTypes;
   2.136 -                if (params1.length == params2.length) {
   2.137 -                    for (int i = 0; i < params1.length; i++) {
   2.138 -                        if (params1[i] != params2[i])
   2.139 -                            return false;
   2.140 -                    }
   2.141 -                    return true;
   2.142 -                }
   2.143 -            }
   2.144 +            return data == other.data;
   2.145          }
   2.146          return false;
   2.147      }
   2.148 @@ -362,6 +309,7 @@
   2.149              sb.append(Field.getTypeName(getReturnType())).append(' ');
   2.150              sb.append(Field.getTypeName(getDeclaringClass())).append('.');
   2.151              sb.append(getName()).append('(');
   2.152 +            /*
   2.153              Class<?>[] params = parameterTypes; // avoid clone
   2.154              for (int j = 0; j < params.length; j++) {
   2.155                  sb.append(Field.getTypeName(params[j]));
   2.156 @@ -378,6 +326,7 @@
   2.157                          sb.append(',');
   2.158                  }
   2.159              }
   2.160 +            */
   2.161              return sb.toString();
   2.162          } catch (Exception e) {
   2.163              return "<" + e + ">";
   2.164 @@ -537,6 +486,10 @@
   2.165       * @exception ExceptionInInitializerError if the initialization
   2.166       * provoked by this method fails.
   2.167       */
   2.168 +    @JavaScriptBody(args = { "method", "self", "args" }, body =
   2.169 +          "if (args.length > 0) throw 'unsupported now';"
   2.170 +        + "return method.fld_data(self);"
   2.171 +    )
   2.172      public Object invoke(Object obj, Object... args)
   2.173          throws IllegalAccessException, IllegalArgumentException,
   2.174             InvocationTargetException
   2.175 @@ -614,8 +567,6 @@
   2.176       * @since  1.5
   2.177       */
   2.178      public Object getDefaultValue() {
   2.179 -        if  (annotationDefault == null)
   2.180 -            return null;
   2.181          throw new UnsupportedOperationException();
   2.182      }
   2.183  
   2.184 @@ -636,10 +587,36 @@
   2.185       * @since 1.5
   2.186       */
   2.187      public Annotation[][] getParameterAnnotations() {
   2.188 -        int numParameters = parameterTypes.length;
   2.189 -        if (parameterAnnotations == null)
   2.190 -            return new Annotation[numParameters][0];
   2.191 -
   2.192          throw new UnsupportedOperationException();
   2.193      }
   2.194 +    
   2.195 +    //
   2.196 +    // bck2brwsr implementation
   2.197 +    //
   2.198 +
   2.199 +    @JavaScriptBody(args = { "clazz", "name", "params" },
   2.200 +        body = "if (params.length > 0) return null;\n"
   2.201 +        + "var c = clazz.cnstr.prototype;"
   2.202 +        + "var prefix = name + '__';\n"
   2.203 +        + "for (m in c) {\n"
   2.204 +        + "  if (m.indexOf(prefix) === 0) {"
   2.205 +        + "     return c[m];\n"
   2.206 +        + "  }"
   2.207 +        + "}\n"
   2.208 +        + "return null;"
   2.209 +    )
   2.210 +    private static native Object findMethodData(
   2.211 +        Class<?> clazz, String name, Class<?>... parameterTypes
   2.212 +    );
   2.213 +    
   2.214 +    // XXX should not be public
   2.215 +    public static Method findMethod(
   2.216 +        Class<?> clazz, String name, Class<?>... parameterTypes
   2.217 +    ) {
   2.218 +        Object data = findMethodData(clazz, name, parameterTypes);
   2.219 +        if (data == null) {
   2.220 +            return null;
   2.221 +        }
   2.222 +        return new Method(clazz, name, data);
   2.223 +    }
   2.224  }