# HG changeset patch # User Jaroslav Tulach # Date 1354628941 -3600 # Node ID 5d1e20215d122710e19cbccc133119be3db26753 # Parent 1d03cb35fbda736c65ad2a22e8af5bbf4269c4fb Test to verify reflective call on a method of a class diff -r 1d03cb35fbda -r 5d1e20215d12 emul/src/main/java/java/lang/Class.java --- a/emul/src/main/java/java/lang/Class.java Tue Dec 04 14:31:11 2012 +0100 +++ b/emul/src/main/java/java/lang/Class.java Tue Dec 04 14:49:01 2012 +0100 @@ -27,6 +27,8 @@ import java.io.InputStream; import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.lang.reflect.TypeVariable; import org.apidesign.bck2brwsr.core.JavaScriptBody; @@ -523,7 +525,231 @@ throw new IllegalStateException("Malformed class name"); } } + + /** + * Returns an array containing {@code Field} objects reflecting all + * the accessible public fields of the class or interface represented by + * this {@code Class} object. The elements in the array returned are + * not sorted and are not in any particular order. This method returns an + * array of length 0 if the class or interface has no accessible public + * fields, or if it represents an array class, a primitive type, or void. + * + *

Specifically, if this {@code Class} object represents a class, + * this method returns the public fields of this class and of all its + * superclasses. If this {@code Class} object represents an + * interface, this method returns the fields of this interface and of all + * its superinterfaces. + * + *

The implicit length field for array class is not reflected by this + * method. User code should use the methods of class {@code Array} to + * manipulate arrays. + * + *

See The Java Language Specification, sections 8.2 and 8.3. + * + * @return the array of {@code Field} objects representing the + * public fields + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

+ * + * @since JDK1.1 + */ + public Field[] getFields() throws SecurityException { + throw new SecurityException(); + } + + /** + * Returns an array containing {@code Method} objects reflecting all + * the public member methods of the class or interface represented + * by this {@code Class} object, including those declared by the class + * or interface and those inherited from superclasses and + * superinterfaces. Array classes return all the (public) member methods + * inherited from the {@code Object} class. The elements in the array + * returned are not sorted and are not in any particular order. This + * method returns an array of length 0 if this {@code Class} object + * represents a class or interface that has no public member methods, or if + * this {@code Class} object represents a primitive type or void. + * + *

The class initialization method {@code } is not + * included in the returned array. If the class declares multiple public + * member methods with the same parameter types, they are all included in + * the returned array. + * + *

See The Java Language Specification, sections 8.2 and 8.4. + * + * @return the array of {@code Method} objects representing the + * public methods of this class + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

+ * + * @since JDK1.1 + */ + public Method[] getMethods() throws SecurityException { + throw new SecurityException(); + } + + /** + * Returns a {@code Field} object that reflects the specified public + * member field of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired field. + * + *

The field to be reflected is determined by the algorithm that + * follows. Let C be the class represented by this object: + *

    + *
  1. If C declares a public field with the name specified, that is the + * field to be reflected.
  2. + *
  3. If no field was found in step 1 above, this algorithm is applied + * recursively to each direct superinterface of C. The direct + * superinterfaces are searched in the order they were declared.
  4. + *
  5. If no field was found in steps 1 and 2 above, and C has a + * superclass S, then this algorithm is invoked recursively upon S. + * If C has no superclass, then a {@code NoSuchFieldException} + * is thrown.
  6. + *
+ * + *

See The Java Language Specification, sections 8.2 and 8.3. + * + * @param name the field name + * @return the {@code Field} object of this class specified by + * {@code name} + * @exception NoSuchFieldException if a field with the specified name is + * not found. + * @exception NullPointerException if {@code name} is {@code null} + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

+ * + * @since JDK1.1 + */ + public Field getField(String name) + throws SecurityException { + throw new SecurityException(); + } + + /** + * Returns a {@code Method} object that reflects the specified public + * member method of the class or interface represented by this + * {@code Class} object. The {@code name} parameter is a + * {@code String} specifying the simple name of the desired method. The + * {@code parameterTypes} parameter is an array of {@code Class} + * objects that identify the method's formal parameter types, in declared + * order. If {@code parameterTypes} is {@code null}, it is + * treated as if it were an empty array. + * + *

If the {@code name} is "{@code };"or "{@code }" a + * {@code NoSuchMethodException} is raised. Otherwise, the method to + * be reflected is determined by the algorithm that follows. Let C be the + * class represented by this object: + *

    + *
  1. C is searched for any matching methods. If no matching + * method is found, the algorithm of step 1 is invoked recursively on + * the superclass of C.
  2. + *
  3. If no method was found in step 1 above, the superinterfaces of C + * are searched for a matching method. If any such method is found, it + * is reflected.
  4. + *
+ * + * To find a matching method in a class C:  If C declares exactly one + * public method with the specified name and exactly the same formal + * parameter types, that is the method reflected. If more than one such + * method is found in C, and one of these methods has a return type that is + * more specific than any of the others, that method is reflected; + * otherwise one of the methods is chosen arbitrarily. + * + *

Note that there may be more than one matching method in a + * class because while the Java language forbids a class to + * declare multiple methods with the same signature but different + * return types, the Java virtual machine does not. This + * increased flexibility in the virtual machine can be used to + * implement various language features. For example, covariant + * returns can be implemented with {@linkplain + * java.lang.reflect.Method#isBridge bridge methods}; the bridge + * method and the method being overridden would have the same + * signature but different return types. + * + *

See The Java Language Specification, sections 8.2 and 8.4. + * + * @param name the name of the method + * @param parameterTypes the list of parameters + * @return the {@code Method} object that matches the specified + * {@code name} and {@code parameterTypes} + * @exception NoSuchMethodException if a matching method is not found + * or if the name is "<init>"or "<clinit>". + * @exception NullPointerException if {@code name} is {@code null} + * @exception SecurityException + * If a security manager, s, is present and any of the + * following conditions is met: + * + *

+ * + * @since JDK1.1 + */ + public Method getMethod(String name, Class... parameterTypes) + throws SecurityException { + throw new SecurityException(); + } + /** * Character.isDigit answers {@code true} to some non-ascii * digits. This one does not. diff -r 1d03cb35fbda -r 5d1e20215d12 vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Tue Dec 04 14:31:11 2012 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Tue Dec 04 14:49:01 2012 +0100 @@ -83,6 +83,15 @@ @Test public void jsStringAnnotationFromArray() throws Exception { assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", false); } + @Test public void javaInvokeMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(true), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsInvokeMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2Z", + "java.io.IOException" + ); + } private static CharSequence codeSeq; private static Invocable code; diff -r 1d03cb35fbda -r 5d1e20215d12 vm/src/test/java/org/apidesign/vm4brwsr/Classes.java --- a/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Tue Dec 04 14:31:11 2012 +0100 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Tue Dec 04 14:49:01 2012 +0100 @@ -19,6 +19,7 @@ import java.io.IOException; import java.lang.annotation.Annotation; +import java.lang.reflect.Method; import java.net.MalformedURLException; /** @@ -41,6 +42,7 @@ return new IOException().getClass().getName().toString(); } + @ClassesMarker(number = 1) public static String name() { return IOException.class.getName().toString(); } @@ -76,4 +78,21 @@ } return null; } + + public static Object reflectiveMethodCall(boolean direct) throws Exception { + Method m; + /* + if (!direct) { + final Class v = ClassesMarker.class; + for (Method single : Classes.class.getMethods()) { + if (single.getAnnotation(v)) { + m = single; + break; + } + } + } else*/ { + m = Classes.class.getMethod("name"); + } + return m.invoke(null); + } }