Reflective calls on methods that return int launcher
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Wed, 19 Dec 2012 16:43:37 +0100
branchlauncher
changeset 354002b7c3d5157
parent 353 fd38bdad7fb5
child 355 eea0065bcc1a
Reflective calls on methods that return int
emul/src/main/java/java/lang/Class.java
emul/src/main/java/java/lang/reflect/Method.java
vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java
vm/src/test/java/org/apidesign/vm4brwsr/Classes.java
     1.1 --- a/emul/src/main/java/java/lang/Class.java	Tue Dec 18 16:04:37 2012 +0100
     1.2 +++ b/emul/src/main/java/java/lang/Class.java	Wed Dec 19 16:43:37 2012 +0100
     1.3 @@ -330,6 +330,10 @@
     1.4       * @see     java.lang.Void#TYPE
     1.5       * @since JDK1.1
     1.6       */
     1.7 +    @JavaScriptBody(args = "self", body = 
     1.8 +           "if (self.primitive) return true;"
     1.9 +        + "else return false;"
    1.10 +    )
    1.11      public native boolean isPrimitive();
    1.12  
    1.13      /**
    1.14 @@ -1093,6 +1097,7 @@
    1.15      @JavaScriptBody(args = "type", body = ""
    1.16          + "var c = vm.java_lang_Class(true);"
    1.17          + "c.jvmName = type;"
    1.18 +        + "c.primitive = true;"
    1.19          + "return c;"
    1.20      )
    1.21      native static Class getPrimitiveClass(String type);
     2.1 --- a/emul/src/main/java/java/lang/reflect/Method.java	Tue Dec 18 16:04:37 2012 +0100
     2.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java	Wed Dec 19 16:43:37 2012 +0100
     2.3 @@ -137,7 +137,24 @@
     2.4       * @return the return type for the method this object represents
     2.5       */
     2.6      public Class<?> getReturnType() {
     2.7 -        throw new UnsupportedOperationException();
     2.8 +        switch (sig.charAt(0)) {
     2.9 +            case 'I': return Integer.TYPE;
    2.10 +            case 'J': return Long.TYPE;
    2.11 +            case 'D': return Double.TYPE;
    2.12 +            case 'F': return Float.TYPE;
    2.13 +            case 'B': return Byte.TYPE;
    2.14 +            case 'Z': return Boolean.TYPE;
    2.15 +            case 'S': return Short.TYPE;
    2.16 +//            case 'V': return Void.TYPE;
    2.17 +            case 'L': try {
    2.18 +                int up = sig.indexOf("_2");
    2.19 +                String type = sig.substring(1, up);
    2.20 +                return Class.forName(type);
    2.21 +            } catch (ClassNotFoundException ex) {
    2.22 +                // should not happen
    2.23 +            }
    2.24 +        }
    2.25 +        throw new UnsupportedOperationException(sig);
    2.26      }
    2.27  
    2.28      /**
    2.29 @@ -488,17 +505,33 @@
    2.30       * @exception ExceptionInInitializerError if the initialization
    2.31       * provoked by this method fails.
    2.32       */
    2.33 +    public Object invoke(Object obj, Object... args)
    2.34 +        throws IllegalAccessException, IllegalArgumentException,
    2.35 +           InvocationTargetException
    2.36 +    {
    2.37 +        Object res = invoke0(this, obj, args);
    2.38 +        if (getReturnType().isPrimitive()) {
    2.39 +            res = fromPrimitive(getReturnType(), res);
    2.40 +        }
    2.41 +        return res;
    2.42 +    }
    2.43 +    
    2.44      @JavaScriptBody(args = { "method", "self", "args" }, body =
    2.45            "if (args.length > 0) throw 'unsupported now';"
    2.46          + "return method.fld_data(self);"
    2.47      )
    2.48 -    public Object invoke(Object obj, Object... args)
    2.49 -        throws IllegalAccessException, IllegalArgumentException,
    2.50 -           InvocationTargetException
    2.51 -    {
    2.52 -        throw new UnsupportedOperationException();
    2.53 +    private static native Object invoke0(Method m, Object self, Object[] args);
    2.54 +
    2.55 +    private static Object fromPrimitive(Class<?> type, Object o) {
    2.56 +        if (type == Integer.TYPE) {
    2.57 +            return fromInteger(o);
    2.58 +        }
    2.59 +        return o;
    2.60      }
    2.61 -
    2.62 +    
    2.63 +    @JavaScriptBody(args = "o", body = "return vm.java_lang_Integer(false).valueOf__Ljava_lang_Integer_2I(o);")
    2.64 +    private static native Integer fromInteger(Object o);
    2.65 +    
    2.66      /**
    2.67       * Returns {@code true} if this method is a bridge
    2.68       * method; returns {@code false} otherwise.
     3.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Tue Dec 18 16:04:37 2012 +0100
     3.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Wed Dec 19 16:43:37 2012 +0100
     3.3 @@ -101,6 +101,12 @@
     3.4              "java.io.IOException", false, "name"
     3.5          );
     3.6      }
     3.7 +    @Test public void primitiveReturnType() throws Exception {
     3.8 +        assertExec("Tries to get an integer via reflection", Classes.class, 
     3.9 +            "primitiveType__Ljava_lang_String_2", 
    3.10 +            Classes.primitiveType()
    3.11 +        );
    3.12 +    }
    3.13      @Test public void javaAnnotatedMethod() throws Exception {
    3.14          assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection");
    3.15      }
     4.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Tue Dec 18 16:04:37 2012 +0100
     4.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Wed Dec 19 16:43:37 2012 +0100
     4.3 @@ -92,6 +92,14 @@
     4.4          return Integer.TYPE.getName();
     4.5      }
     4.6      
     4.7 +    public static int primitive() {
     4.8 +        return 1;
     4.9 +    }
    4.10 +    
    4.11 +    public static String primitiveType() throws Exception {
    4.12 +        return reflectiveMethodCall(false, "primitive").getClass().getName();
    4.13 +    }
    4.14 +    
    4.15      @JavaScriptBody(args = "msg", body = "throw msg;")
    4.16      private static native void thrw(String msg);
    4.17