# HG changeset patch # User Jaroslav Tulach # Date 1354701170 -3600 # Node ID 79697fa91bfc7c2adb7401d5ff476ee81173a46d # Parent 0bfcb658529097fe8f86b56265f206ca8229f295# Parent 2e2e6f946208fa38d21826b0c3ffe7f515b345db Merging in reflection work. Seems to be solid now. diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/Class.java --- a/emul/src/main/java/java/lang/Class.java Tue Dec 04 09:16:53 2012 +0100 +++ b/emul/src/main/java/java/lang/Class.java Wed Dec 05 10:52:50 2012 +0100 @@ -25,8 +25,13 @@ package java.lang; +import org.apidesign.bck2brwsr.emul.AnnotationImpl; 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; /** * Instances of the class {@code Class} represent classes and @@ -74,10 +79,10 @@ * @since JDK1.0 */ public final - class Class implements java.io.Serializable { -// java.lang.reflect.GenericDeclaration, -// java.lang.reflect.Type, -// java.lang.reflect.AnnotatedElement { + class Class implements java.io.Serializable, + java.lang.reflect.GenericDeclaration, + java.lang.reflect.Type, + java.lang.reflect.AnnotatedElement { private static final int ANNOTATION= 0x00002000; private static final int ENUM = 0x00004000; private static final int SYNTHETIC = 0x00001000; @@ -190,10 +195,15 @@ * * */ + @JavaScriptBody(args = "self", body = + "var inst = self.cnstr();" + + "inst.cons__V(inst);" + + "return inst;" + ) public T newInstance() throws InstantiationException, IllegalAccessException { - throw new UnsupportedOperationException("Should be somehow supported"); + throw new UnsupportedOperationException(); } /** @@ -273,7 +283,9 @@ * {@code false} otherwise. * @since JDK1.1 */ - public native boolean isArray(); + public boolean isArray() { + return false; + } /** @@ -382,13 +394,32 @@ * represented by this object. */ public String getName() { - throw new UnsupportedOperationException(); -// String name = this.name; -// if (name == null) -// this.name = name = getName0(); -// return name; + return jvmName().replace('/', '.'); } + @JavaScriptBody(args = "self", body = "return self.jvmName;") + private native String jvmName(); + + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws java.lang.reflect.GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + * @since 1.5 + */ + public TypeVariable>[] getTypeParameters() { + throw new UnsupportedOperationException(); + } + /** * Returns the {@code Class} representing the superclass of the entity * (class, interface, primitive type or void) represented by this @@ -400,6 +431,7 @@ * * @return the superclass of the class represented by this object. */ + @JavaScriptBody(args = "self", body = "return self.superclass;") public native Class getSuperclass(); /** @@ -445,37 +477,282 @@ * @since 1.5 */ public String getSimpleName() { - throw new UnsupportedOperationException(); -//// if (isArray()) -//// return getComponentType().getSimpleName()+"[]"; -//// -//// String simpleName = getSimpleBinaryName(); -//// if (simpleName == null) { // top level class -//// simpleName = getName(); -//// return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name -//// } -//// // According to JLS3 "Binary Compatibility" (13.1) the binary -//// // name of non-package classes (not top level) is the binary -//// // name of the immediately enclosing class followed by a '$' followed by: -//// // (for nested and inner classes): the simple name. -//// // (for local classes): 1 or more digits followed by the simple name. -//// // (for anonymous classes): 1 or more digits. -//// -//// // Since getSimpleBinaryName() will strip the binary name of -//// // the immediatly enclosing class, we are now looking at a -//// // string that matches the regular expression "\$[0-9]*" -//// // followed by a simple name (considering the simple of an -//// // anonymous class to be the empty string). -//// -//// // Remove leading "\$[0-9]*" from the name -//// int length = simpleName.length(); -//// if (length < 1 || simpleName.charAt(0) != '$') -//// throw new InternalError("Malformed class name"); -//// int index = 1; -//// while (index < length && isAsciiDigit(simpleName.charAt(index))) -//// index++; -//// // Eventually, this is the empty string iff this is an anonymous class -//// return simpleName.substring(index); + if (isArray()) + return getComponentType().getSimpleName()+"[]"; + + String simpleName = getSimpleBinaryName(); + if (simpleName == null) { // top level class + simpleName = getName(); + return simpleName.substring(simpleName.lastIndexOf(".")+1); // strip the package name + } + // According to JLS3 "Binary Compatibility" (13.1) the binary + // name of non-package classes (not top level) is the binary + // name of the immediately enclosing class followed by a '$' followed by: + // (for nested and inner classes): the simple name. + // (for local classes): 1 or more digits followed by the simple name. + // (for anonymous classes): 1 or more digits. + + // Since getSimpleBinaryName() will strip the binary name of + // the immediatly enclosing class, we are now looking at a + // string that matches the regular expression "\$[0-9]*" + // followed by a simple name (considering the simple of an + // anonymous class to be the empty string). + + // Remove leading "\$[0-9]*" from the name + int length = simpleName.length(); + if (length < 1 || simpleName.charAt(0) != '$') + throw new IllegalStateException("Malformed class name"); + int index = 1; + while (index < length && isAsciiDigit(simpleName.charAt(index))) + index++; + // Eventually, this is the empty string iff this is an anonymous class + return simpleName.substring(index); + } + + /** + * Returns the "simple binary name" of the underlying class, i.e., + * the binary name without the leading enclosing class name. + * Returns {@code null} if the underlying class is a top level + * class. + */ + private String getSimpleBinaryName() { + Class enclosingClass = null; // XXX getEnclosingClass(); + if (enclosingClass == null) // top level class + return null; + // Otherwise, strip the enclosing class' name + try { + return getName().substring(enclosingClass.getName().length()); + } catch (IndexOutOfBoundsException ex) { + 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: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the fields within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @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: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the methods within this class + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Method[] getMethods() throws SecurityException { + return Method.findMethods(this); + } + + /** + * 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: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the field + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @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: + * + *

    + * + *
  • invocation of + * {@link SecurityManager#checkMemberAccess + * s.checkMemberAccess(this, Member.PUBLIC)} denies + * access to the method + * + *
  • the caller's class loader is not the same as or an + * ancestor of the class loader for the current class and + * invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the package + * of this class + * + *
+ * + * @since JDK1.1 + */ + public Method getMethod(String name, Class... parameterTypes) + throws SecurityException { + Method m = Method.findMethod(this, name, parameterTypes); + if (m == null) { + throw new SecurityException(); // XXX: NoSuchMethodException + } + return m; } /** @@ -497,25 +774,25 @@ * @since 1.5 */ public String getCanonicalName() { - throw new UnsupportedOperationException(); -// if (isArray()) { -// String canonicalName = getComponentType().getCanonicalName(); -// if (canonicalName != null) -// return canonicalName + "[]"; -// else -// return null; -// } + if (isArray()) { + String canonicalName = getComponentType().getCanonicalName(); + if (canonicalName != null) + return canonicalName + "[]"; + else + return null; + } // if (isLocalOrAnonymousClass()) // return null; // Class enclosingClass = getEnclosingClass(); -// if (enclosingClass == null) { // top level class -// return getName(); -// } else { -// String enclosingName = enclosingClass.getCanonicalName(); -// if (enclosingName == null) -// return null; -// return enclosingName + "." + getSimpleName(); -// } + Class enclosingClass = null; + if (enclosingClass == null) { // top level class + return getName(); + } else { + String enclosingName = enclosingClass.getCanonicalName(); + if (enclosingName == null) + return null; + return enclosingName + "." + getSimpleName(); + } } /** @@ -676,7 +953,9 @@ * @see java.lang.reflect.Array * @since JDK1.1 */ - public native Class getComponentType(); + public Class getComponentType() { + return null; + } /** * Returns true if and only if this class was declared as an enum in the @@ -743,18 +1022,32 @@ throw new ClassCastException(this.toString()); } + @JavaScriptBody(args = { "self", "ac" }, + body = + "if (self.anno) {" + + " return self.anno['L' + ac.jvmName + ';'];" + + "} else return null;" + ) + private Object getAnnotationData(Class annotationClass) { + throw new UnsupportedOperationException(); + } /** * @throws NullPointerException {@inheritDoc} * @since 1.5 */ public A getAnnotation(Class annotationClass) { - throw new UnsupportedOperationException(); + Object data = getAnnotationData(annotationClass); + return data == null ? null : AnnotationImpl.create(annotationClass, data); } /** * @throws NullPointerException {@inheritDoc} * @since 1.5 */ + @JavaScriptBody(args = { "self", "ac" }, + body = "if (self.anno && self.anno['L' + ac.jvmName + ';']) { return true; }" + + "else return false;" + ) public boolean isAnnotationPresent( Class annotationClass) { if (annotationClass == null) @@ -763,12 +1056,17 @@ return getAnnotation(annotationClass) != null; } + @JavaScriptBody(args = "self", body = "return self.anno;") + private Object getAnnotationData() { + throw new UnsupportedOperationException(); + } /** * @since 1.5 */ public Annotation[] getAnnotations() { - throw new UnsupportedOperationException(); + Object data = getAnnotationData(); + return data == null ? new Annotation[0] : AnnotationImpl.create(data); } /** diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/Object.java --- a/emul/src/main/java/java/lang/Object.java Tue Dec 04 09:16:53 2012 +0100 +++ b/emul/src/main/java/java/lang/Object.java Wed Dec 05 10:52:50 2012 +0100 @@ -66,6 +66,7 @@ * @see Class Literals, section 15.8.2 of * The Java™ Language Specification. */ + @JavaScriptBody(args="self", body="return self.constructor.$class;") public final native Class getClass(); /** diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/String.java --- a/emul/src/main/java/java/lang/String.java Tue Dec 04 09:16:53 2012 +0100 +++ b/emul/src/main/java/java/lang/String.java Wed Dec 05 10:52:50 2012 +0100 @@ -1691,6 +1691,10 @@ * than or equal to fromIndex, or -1 * if the character does not occur before that point. */ + @JavaScriptBody(args = { "self", "ch", "from" }, body = + "if (typeof ch === 'number') ch = String.fromCharCode(ch);\n" + + "return self.toString().lastIndexOf(ch, from);" + ) public int lastIndexOf(int ch, int fromIndex) { if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a @@ -1763,7 +1767,7 @@ * or {@code -1} if there is no such occurrence. */ @JavaScriptBody(args = { "self", "str", "fromIndex" }, body = - "return self.toString().indexOf(str.toString(), fromIndex) >= 0;" + "return self.toString().indexOf(str.toString(), fromIndex);" ) public int indexOf(String str, int fromIndex) { return indexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex); @@ -1855,6 +1859,9 @@ * searching backward from the specified index, * or {@code -1} if there is no such occurrence. */ + @JavaScriptBody(args = { "self", "s", "from" }, body = + "return self.toString().lastIndexOf(s.toString(), from);" + ) public int lastIndexOf(String str, int fromIndex) { return lastIndexOf(toCharArray(), offset(), length(), str.toCharArray(), str.offset(), str.length(), fromIndex); } diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/Throwable.java --- a/emul/src/main/java/java/lang/Throwable.java Tue Dec 04 09:16:53 2012 +0100 +++ b/emul/src/main/java/java/lang/Throwable.java Wed Dec 05 10:52:50 2012 +0100 @@ -25,6 +25,7 @@ package java.lang; import java.io.*; +import org.apidesign.bck2brwsr.core.JavaScriptBody; /** * The {@code Throwable} class is the superclass of all errors and @@ -782,6 +783,7 @@ return this; } + @JavaScriptBody(args = { "self", "dummy" }, body = "") private native Throwable fillInStackTrace(int dummy); /** diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/AccessibleObject.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/AccessibleObject.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +/** + * The AccessibleObject class is the base class for Field, Method and + * Constructor objects. It provides the ability to flag a reflected + * object as suppressing default Java language access control checks + * when it is used. The access checks--for public, default (package) + * access, protected, and private members--are performed when Fields, + * Methods or Constructors are used to set or get fields, to invoke + * methods, or to create and initialize new instances of classes, + * respectively. + * + *

Setting the {@code accessible} flag in a reflected object + * permits sophisticated applications with sufficient privilege, such + * as Java Object Serialization or other persistence mechanisms, to + * manipulate objects in a manner that would normally be prohibited. + * + *

By default, a reflected object is not accessible. + * + * @see Field + * @see Method + * @see Constructor + * @see ReflectPermission + * + * @since 1.2 + */ +public class AccessibleObject implements AnnotatedElement { + + /** + * Convenience method to set the {@code accessible} flag for an + * array of objects with a single security check (for efficiency). + * + *

First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of any of the elements of the input + * {@code array} may not be changed (for example, if the element + * object is a {@link Constructor} object for the class {@link + * java.lang.Class}). In the event of such a SecurityException, the + * accessibility of objects is set to {@code flag} for array elements + * upto (and excluding) the element for which the exception occurred; the + * accessibility of elements beyond (and including) the element for which + * the exception occurred is unchanged. + * + * @param array the array of AccessibleObjects + * @param flag the new value for the {@code accessible} flag + * in each object + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public static void setAccessible(AccessibleObject[] array, boolean flag) + throws SecurityException { + throw new SecurityException(); + } + + /** + * Set the {@code accessible} flag for this object to + * the indicated boolean value. A value of {@code true} indicates that + * the reflected object should suppress Java language access + * checking when it is used. A value of {@code false} indicates + * that the reflected object should enforce Java language access checks. + * + *

First, if there is a security manager, its + * {@code checkPermission} method is called with a + * {@code ReflectPermission("suppressAccessChecks")} permission. + * + *

A {@code SecurityException} is raised if {@code flag} is + * {@code true} but accessibility of this object may not be changed + * (for example, if this element object is a {@link Constructor} object for + * the class {@link java.lang.Class}). + * + *

A {@code SecurityException} is raised if this object is a {@link + * java.lang.reflect.Constructor} object for the class + * {@code java.lang.Class}, and {@code flag} is true. + * + * @param flag the new value for the {@code accessible} flag + * @throws SecurityException if the request is denied. + * @see SecurityManager#checkPermission + * @see java.lang.RuntimePermission + */ + public void setAccessible(boolean flag) throws SecurityException { + throw new SecurityException(); + } + + /** + * Get the value of the {@code accessible} flag for this object. + * + * @return the value of the object's {@code accessible} flag + */ + public boolean isAccessible() { + return override; + } + + /** + * Constructor: only used by the Java Virtual Machine. + */ + protected AccessibleObject() {} + + // Indicates whether language-level access checks are overridden + // by this object. Initializes to "false". This field is used by + // Field, Method, and Constructor. + // + // NOTE: for security purposes, this field must not be visible + // outside this package. + boolean override; + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + throw new AssertionError("All subclasses should override this method"); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public boolean isAnnotationPresent( + Class annotationClass) { + return getAnnotation(annotationClass) != null; + } + + /** + * @since 1.5 + */ + public Annotation[] getAnnotations() { + return getDeclaredAnnotations(); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new AssertionError("All subclasses should override this method"); + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/AnnotatedElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/AnnotatedElement.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + +/** + * Represents an annotated element of the program currently running in this + * VM. This interface allows annotations to be read reflectively. All + * annotations returned by methods in this interface are immutable and + * serializable. It is permissible for the caller to modify the + * arrays returned by accessors for array-valued enum members; it will + * have no affect on the arrays returned to other callers. + * + *

If an annotation returned by a method in this interface contains + * (directly or indirectly) a {@link Class}-valued member referring to + * a class that is not accessible in this VM, attempting to read the class + * by calling the relevant Class-returning method on the returned annotation + * will result in a {@link TypeNotPresentException}. + * + *

Similarly, attempting to read an enum-valued member will result in + * a {@link EnumConstantNotPresentException} if the enum constant in the + * annotation is no longer present in the enum type. + * + *

Finally, Attempting to read a member whose definition has evolved + * incompatibly will result in a {@link + * java.lang.annotation.AnnotationTypeMismatchException} or an + * {@link java.lang.annotation.IncompleteAnnotationException}. + * + * @see java.lang.EnumConstantNotPresentException + * @see java.lang.TypeNotPresentException + * @see java.lang.annotation.AnnotationFormatError + * @see java.lang.annotation.AnnotationTypeMismatchException + * @see java.lang.annotation.IncompleteAnnotationException + * @since 1.5 + * @author Josh Bloch + */ +public interface AnnotatedElement { + /** + * Returns true if an annotation for the specified type + * is present on this element, else false. This method + * is designed primarily for convenient access to marker annotations. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return true if an annotation for the specified annotation + * type is present on this element, else false + * @throws NullPointerException if the given annotation class is null + * @since 1.5 + */ + boolean isAnnotationPresent(Class annotationClass); + + /** + * Returns this element's annotation for the specified type if + * such an annotation is present, else null. + * + * @param annotationClass the Class object corresponding to the + * annotation type + * @return this element's annotation for the specified annotation type if + * present on this element, else null + * @throws NullPointerException if the given annotation class is null + * @since 1.5 + */ + T getAnnotation(Class annotationClass); + + /** + * Returns all annotations present on this element. (Returns an array + * of length zero if this element has no annotations.) The caller of + * this method is free to modify the returned array; it will have no + * effect on the arrays returned to other callers. + * + * @return all annotations present on this element + * @since 1.5 + */ + Annotation[] getAnnotations(); + + /** + * Returns all annotations that are directly present on this + * element. Unlike the other methods in this interface, this method + * ignores inherited annotations. (Returns an array of length zero if + * no annotations are directly present on this element.) The caller of + * this method is free to modify the returned array; it will have no + * effect on the arrays returned to other callers. + * + * @return All annotations directly present on this element + * @since 1.5 + */ + Annotation[] getDeclaredAnnotations(); +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/Field.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Field.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,953 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; + + +/** + * A {@code Field} provides information about, and dynamic access to, a + * single field of a class or an interface. The reflected field may + * be a class (static) field or an instance field. + * + *

A {@code Field} permits widening conversions to occur during a get or + * set access operation, but throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getFields() + * @see java.lang.Class#getField(String) + * @see java.lang.Class#getDeclaredFields() + * @see java.lang.Class#getDeclaredField(String) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final +class Field extends AccessibleObject implements Member { + + private Class clazz; + private int slot; + // This is guaranteed to be interned by the VM in the 1.4 + // reflection implementation + private String name; + private Class type; + private int modifiers; + // Generics and annotations support + private transient String signature; + private byte[] annotations; + // For sharing of FieldAccessors. This branching structure is + // currently only two levels deep (i.e., one root Field and + // potentially many Field objects pointing to it.) + private Field root; + + // Generics infrastructure + + private String getGenericSignature() {return signature;} + + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Field(Class declaringClass, + String name, + Class type, + int modifiers, + int slot, + String signature, + byte[] annotations) + { + this.clazz = declaringClass; + this.name = name; + this.type = type; + this.modifiers = modifiers; + this.slot = slot; + this.signature = signature; + this.annotations = annotations; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Field. The copy's + * "root" field points to this Field. + */ + Field copy() { + // This routine enables sharing of FieldAccessor objects + // among Field objects which refer to the same underlying + // method in the VM. (All of this contortion is only necessary + // because of the "accessibility" bit in AccessibleObject, + // which implicitly requires that new java.lang.reflect + // objects be fabricated for each reflective call on Class + // objects.) + Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations); + res.root = this; + return res; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the field represented by this {@code Field} object. + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the field represented by this {@code Field} object. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the field represented + * by this {@code Field} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns {@code true} if this field represents an element of + * an enumerated type; returns {@code false} otherwise. + * + * @return {@code true} if and only if this field represents an element of + * an enumerated type. + * @since 1.5 + */ + public boolean isEnumConstant() { + return (getModifiers() & Modifier.ENUM) != 0; + } + + /** + * Returns {@code true} if this field is a synthetic + * field; returns {@code false} otherwise. + * + * @return true if and only if this field is a synthetic + * field as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + /** + * Returns a {@code Class} object that identifies the + * declared type for the field represented by this + * {@code Field} object. + * + * @return a {@code Class} object identifying the declared + * type of the field represented by this object + */ + public Class getType() { + return type; + } + + /** + * Returns a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object. + * + *

If the {@code Type} is a parameterized type, the + * {@code Type} object returned must accurately reflect the + * actual type parameters used in the source code. + * + *

If the type of the underlying field is a type variable or a + * parameterized type, it is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the declared type for + * the field represented by this {@code Field} object + * @throws GenericSignatureFormatError if the generic field + * signature does not conform to the format specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the generic type + * signature of the underlying field refers to a non-existent + * type declaration + * @throws MalformedParameterizedTypeException if the generic + * signature of the underlying field refers to a parameterized type + * that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericType() { + throw new UnsupportedOperationException(); + } + + + /** + * Compares this {@code Field} against the specified object. Returns + * true if the objects are the same. Two {@code Field} objects are the same if + * they were declared by the same class and have the same name + * and type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Field) { + Field other = (Field)obj; + return (getDeclaringClass() == other.getDeclaringClass()) + && (getName() == other.getName()) + && (getType() == other.getType()); + } + return false; + } + + /** + * Returns a hashcode for this {@code Field}. This is computed as the + * exclusive-or of the hashcodes for the underlying field's + * declaring class name and its name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Field}. The format is + * the access modifiers for the field, if any, followed + * by the field type, followed by a space, followed by + * the fully-qualified name of the class declaring the field, + * followed by a period, followed by the name of the field. + * For example: + *

+     *    public static final int java.lang.Thread.MIN_PRIORITY
+     *    private int java.io.FileDescriptor.fd
+     * 
+ * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + */ + public String toString() { + int mod = getModifiers(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + getTypeName(getType()) + " " + + getTypeName(getDeclaringClass()) + "." + + getName()); + } + + /** + * Returns a string describing this {@code Field}, including + * its generic type. The format is the access modifiers for the + * field, if any, followed by the generic field type, followed by + * a space, followed by the fully-qualified name of the class + * declaring the field, followed by a period, followed by the name + * of the field. + * + *

The modifiers are placed in canonical order as specified by + * "The Java Language Specification". This is {@code public}, + * {@code protected} or {@code private} first, and then other + * modifiers in the following order: {@code static}, {@code final}, + * {@code transient}, {@code volatile}. + * + * @return a string describing this {@code Field}, including + * its generic type + * + * @since 1.5 + */ + public String toGenericString() { + int mod = getModifiers(); + Type fieldType = getGenericType(); + return (((mod == 0) ? "" : (Modifier.toString(mod) + " ")) + + ((fieldType instanceof Class) ? + getTypeName((Class)fieldType): fieldType.toString())+ " " + + getTypeName(getDeclaringClass()) + "." + + getName()); + } + + /** + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + *

The underlying field's value is obtained as follows: + * + *

If the underlying field is a static field, the {@code obj} argument + * is ignored; it may be null. + * + *

Otherwise, the underlying field is an instance field. If the + * specified {@code obj} argument is null, the method throws a + * {@code NullPointerException}. If the specified object is not an + * instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

Otherwise, the value is retrieved from the underlying instance + * or static field. If the field has a primitive type, the value + * is wrapped in an object before being returned, otherwise it is + * returned as is. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is obtained according to the preceding rules. + * + * @param obj object from which the represented field's value is + * to be extracted + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof). + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + public Object get(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).get(obj); + } + + /** + * Gets the value of a static or instance {@code boolean} field. + * + * @param obj the object to extract the {@code boolean} value + * from + * @return the value of the {@code boolean} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code boolean} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public boolean getBoolean(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getBoolean(obj); + } + + /** + * Gets the value of a static or instance {@code byte} field. + * + * @param obj the object to extract the {@code byte} value + * from + * @return the value of the {@code byte} field + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code byte} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public byte getByte(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getByte(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code char} or of another primitive type convertible to + * type {@code char} via a widening conversion. + * + * @param obj the object to extract the {@code char} value + * from + * @return the value of the field converted to type {@code char} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code char} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public char getChar(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getChar(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code short} or of another primitive type convertible to + * type {@code short} via a widening conversion. + * + * @param obj the object to extract the {@code short} value + * from + * @return the value of the field converted to type {@code short} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code short} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public short getShort(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getShort(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code int} or of another primitive type convertible to + * type {@code int} via a widening conversion. + * + * @param obj the object to extract the {@code int} value + * from + * @return the value of the field converted to type {@code int} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code int} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public int getInt(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getInt(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code long} or of another primitive type convertible to + * type {@code long} via a widening conversion. + * + * @param obj the object to extract the {@code long} value + * from + * @return the value of the field converted to type {@code long} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code long} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public long getLong(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getLong(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code float} or of another primitive type convertible to + * type {@code float} via a widening conversion. + * + * @param obj the object to extract the {@code float} value + * from + * @return the value of the field converted to type {@code float} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code float} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public float getFloat(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getFloat(obj); + } + + /** + * Gets the value of a static or instance field of type + * {@code double} or of another primitive type convertible to + * type {@code double} via a widening conversion. + * + * @param obj the object to extract the {@code double} value + * from + * @return the value of the field converted to type {@code double} + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is inaccessible. + * @exception IllegalArgumentException if the specified object is not + * an instance of the class or interface declaring the + * underlying field (or a subclass or implementor + * thereof), or if the field value cannot be + * converted to the type {@code double} by a + * widening conversion. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#get + */ + public double getDouble(Object obj) + throws IllegalArgumentException, IllegalAccessException + { + return getFieldAccessor(obj).getDouble(obj); + } + + /** + * Sets the field represented by this {@code Field} object on the + * specified object argument to the specified new value. The new + * value is automatically unwrapped if the underlying field has a + * primitive type. + * + *

The operation proceeds as follows: + * + *

If the underlying field is static, the {@code obj} argument is + * ignored; it may be null. + * + *

Otherwise the underlying field is an instance field. If the + * specified object argument is null, the method throws a + * {@code NullPointerException}. If the specified object argument is not + * an instance of the class or interface declaring the underlying + * field, the method throws an {@code IllegalArgumentException}. + * + *

If this {@code Field} object is enforcing Java language access control, and + * the underlying field is inaccessible, the method throws an + * {@code IllegalAccessException}. + * + *

If the underlying field is final, the method throws an + * {@code IllegalAccessException} unless {@code setAccessible(true)} + * has succeeded for this {@code Field} object + * and the field is non-static. Setting a final field in this way + * is meaningful only during deserialization or reconstruction of + * instances of classes with blank final fields, before they are + * made available for access by other parts of a program. Use in + * any other context may have unpredictable effects, including cases + * in which other parts of a program continue to use the original + * value of this field. + * + *

If the underlying field is of a primitive type, an unwrapping + * conversion is attempted to convert the new value to a value of + * a primitive type. If this attempt fails, the method throws an + * {@code IllegalArgumentException}. + * + *

If, after possible unwrapping, the new value cannot be + * converted to the type of the underlying field by an identity or + * widening conversion, the method throws an + * {@code IllegalArgumentException}. + * + *

If the underlying field is static, the class that declared the + * field is initialized if it has not already been initialized. + * + *

The field is set to the possibly unwrapped and widened new value. + * + *

If the field is hidden in the type of {@code obj}, + * the field's value is set according to the preceding rules. + * + * @param obj the object whose field should be modified + * @param value the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + */ + public void set(Object obj, Object value) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).set(obj, value); + } + + /** + * Sets the value of a field as a {@code boolean} on the specified object. + * This method is equivalent to + * {@code set(obj, zObj)}, + * where {@code zObj} is a {@code Boolean} object and + * {@code zObj.booleanValue() == z}. + * + * @param obj the object whose field should be modified + * @param z the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setBoolean(Object obj, boolean z) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setBoolean(obj, z); + } + + /** + * Sets the value of a field as a {@code byte} on the specified object. + * This method is equivalent to + * {@code set(obj, bObj)}, + * where {@code bObj} is a {@code Byte} object and + * {@code bObj.byteValue() == b}. + * + * @param obj the object whose field should be modified + * @param b the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setByte(Object obj, byte b) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setByte(obj, b); + } + + /** + * Sets the value of a field as a {@code char} on the specified object. + * This method is equivalent to + * {@code set(obj, cObj)}, + * where {@code cObj} is a {@code Character} object and + * {@code cObj.charValue() == c}. + * + * @param obj the object whose field should be modified + * @param c the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setChar(Object obj, char c) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setChar(obj, c); + } + + /** + * Sets the value of a field as a {@code short} on the specified object. + * This method is equivalent to + * {@code set(obj, sObj)}, + * where {@code sObj} is a {@code Short} object and + * {@code sObj.shortValue() == s}. + * + * @param obj the object whose field should be modified + * @param s the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setShort(Object obj, short s) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setShort(obj, s); + } + + /** + * Sets the value of a field as an {@code int} on the specified object. + * This method is equivalent to + * {@code set(obj, iObj)}, + * where {@code iObj} is a {@code Integer} object and + * {@code iObj.intValue() == i}. + * + * @param obj the object whose field should be modified + * @param i the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setInt(Object obj, int i) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setInt(obj, i); + } + + /** + * Sets the value of a field as a {@code long} on the specified object. + * This method is equivalent to + * {@code set(obj, lObj)}, + * where {@code lObj} is a {@code Long} object and + * {@code lObj.longValue() == l}. + * + * @param obj the object whose field should be modified + * @param l the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setLong(Object obj, long l) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setLong(obj, l); + } + + /** + * Sets the value of a field as a {@code float} on the specified object. + * This method is equivalent to + * {@code set(obj, fObj)}, + * where {@code fObj} is a {@code Float} object and + * {@code fObj.floatValue() == f}. + * + * @param obj the object whose field should be modified + * @param f the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setFloat(Object obj, float f) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setFloat(obj, f); + } + + /** + * Sets the value of a field as a {@code double} on the specified object. + * This method is equivalent to + * {@code set(obj, dObj)}, + * where {@code dObj} is a {@code Double} object and + * {@code dObj.doubleValue() == d}. + * + * @param obj the object whose field should be modified + * @param d the new value for the field of {@code obj} + * being modified + * + * @exception IllegalAccessException if this {@code Field} object + * is enforcing Java language access control and the underlying + * field is either inaccessible or final. + * @exception IllegalArgumentException if the specified object is not an + * instance of the class or interface declaring the underlying + * field (or a subclass or implementor thereof), + * or if an unwrapping conversion fails. + * @exception NullPointerException if the specified object is null + * and the field is an instance field. + * @exception ExceptionInInitializerError if the initialization provoked + * by this method fails. + * @see Field#set + */ + public void setDouble(Object obj, double d) + throws IllegalArgumentException, IllegalAccessException + { + getFieldAccessor(obj).setDouble(obj, d); + } + + // Convenience routine which performs security checks + private FieldAccessor getFieldAccessor(Object obj) + throws IllegalAccessException + { + throw new SecurityException(); + } + + private static abstract class FieldAccessor { + abstract void setShort(Object obj, short s); + abstract void setInt(Object obj, int i); + abstract void setChar(Object obj, char c); + abstract void setByte(Object obj, byte b); + abstract void setBoolean(Object obj, boolean z); + abstract void set(Object obj, Object value); + abstract double getDouble(Object obj); + abstract void setLong(Object obj, long l); + abstract void setFloat(Object obj, float f); + abstract void setDouble(Object obj, double d); + abstract long getLong(Object obj); + abstract int getInt(Object obj); + abstract short getShort(Object obj); + abstract char getChar(Object obj); + abstract byte getByte(Object obj); + abstract boolean getBoolean(Object obj); + abstract Object get(Object obj); + abstract float getFloat(Object obj); + } + + /* + * Utility routine to paper over array type names + */ + static String getTypeName(Class type) { + if (type.isArray()) { + try { + Class cl = type; + int dimensions = 0; + while (cl.isArray()) { + dimensions++; + cl = cl.getComponentType(); + } + StringBuffer sb = new StringBuffer(); + sb.append(cl.getName()); + for (int i = 0; i < dimensions; i++) { + sb.append("[]"); + } + return sb.toString(); + } catch (Throwable e) { /*FALLTHRU*/ } + } + return type.getName(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + if (annotationClass == null) + throw new NullPointerException(); + + throw new UnsupportedOperationException(); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/GenericDeclaration.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/GenericDeclaration.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * A common interface for all entities that declare type variables. + * + * @since 1.5 + */ +public interface GenericDeclaration { + /** + * Returns an array of {@code TypeVariable} objects that + * represent the type variables declared by the generic + * declaration represented by this {@code GenericDeclaration} + * object, in declaration order. Returns an array of length 0 if + * the underlying generic declaration declares no type variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + */ + public TypeVariable[] getTypeParameters(); +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/InvocationTargetException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/InvocationTargetException.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1996, 2004, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * InvocationTargetException is a checked exception that wraps + * an exception thrown by an invoked method or constructor. + * + *

As of release 1.4, this exception has been retrofitted to conform to + * the general purpose exception-chaining mechanism. The "target exception" + * that is provided at construction time and accessed via the + * {@link #getTargetException()} method is now known as the cause, + * and may be accessed via the {@link Throwable#getCause()} method, + * as well as the aforementioned "legacy method." + * + * @see Method + * @see Constructor + */ +public class InvocationTargetException extends ReflectiveOperationException { + /** + * Use serialVersionUID from JDK 1.1.X for interoperability + */ + private static final long serialVersionUID = 4085088731926701167L; + + /** + * This field holds the target if the + * InvocationTargetException(Throwable target) constructor was + * used to instantiate the object + * + * @serial + * + */ + private Throwable target; + + /** + * Constructs an {@code InvocationTargetException} with + * {@code null} as the target exception. + */ + protected InvocationTargetException() { + super((Throwable)null); // Disallow initCause + } + + /** + * Constructs a InvocationTargetException with a target exception. + * + * @param target the target exception + */ + public InvocationTargetException(Throwable target) { + super((Throwable)null); // Disallow initCause + this.target = target; + } + + /** + * Constructs a InvocationTargetException with a target exception + * and a detail message. + * + * @param target the target exception + * @param s the detail message + */ + public InvocationTargetException(Throwable target, String s) { + super(s, null); // Disallow initCause + this.target = target; + } + + /** + * Get the thrown target exception. + * + *

This method predates the general-purpose exception chaining facility. + * The {@link Throwable#getCause()} method is now the preferred means of + * obtaining this information. + * + * @return the thrown target exception (cause of this exception). + */ + public Throwable getTargetException() { + return target; + } + + /** + * Returns the cause of this exception (the thrown target exception, + * which may be {@code null}). + * + * @return the cause of this exception. + * @since 1.4 + */ + public Throwable getCause() { + return target; + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/Member.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Member.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Member is an interface that reflects identifying information about + * a single member (a field or a method) or a constructor. + * + * @see java.lang.Class + * @see Field + * @see Method + * @see Constructor + * + * @author Nakul Saraiya + */ +public +interface Member { + + /** + * Identifies the set of all public members of a class or interface, + * including inherited members. + * @see java.lang.SecurityManager#checkMemberAccess + */ + public static final int PUBLIC = 0; + + /** + * Identifies the set of declared members of a class or interface. + * Inherited members are not included. + * @see java.lang.SecurityManager#checkMemberAccess + */ + public static final int DECLARED = 1; + + /** + * Returns the Class object representing the class or interface + * that declares the member or constructor represented by this Member. + * + * @return an object representing the declaring class of the + * underlying member + */ + public Class getDeclaringClass(); + + /** + * Returns the simple name of the underlying member or constructor + * represented by this Member. + * + * @return the simple name of the underlying member + */ + public String getName(); + + /** + * Returns the Java language modifiers for the member or + * constructor represented by this Member, as an integer. The + * Modifier class should be used to decode the modifiers in + * the integer. + * + * @return the Java language modifiers for the underlying member + * @see Modifier + */ + public int getModifiers(); + + /** + * Returns {@code true} if this member was introduced by + * the compiler; returns {@code false} otherwise. + * + * @return true if and only if this member was introduced by + * the compiler. + * @since 1.5 + */ + public boolean isSynthetic(); +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/Method.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Method.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,655 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +import java.lang.annotation.Annotation; +import org.apidesign.bck2brwsr.core.JavaScriptBody; +import org.apidesign.bck2brwsr.emul.AnnotationImpl; + +/** + * A {@code Method} provides information about, and access to, a single method + * on a class or interface. The reflected method may be a class method + * or an instance method (including an abstract method). + * + *

A {@code Method} permits widening conversions to occur when matching the + * actual parameters to invoke with the underlying method's formal + * parameters, but it throws an {@code IllegalArgumentException} if a + * narrowing conversion would occur. + * + * @see Member + * @see java.lang.Class + * @see java.lang.Class#getMethods() + * @see java.lang.Class#getMethod(String, Class[]) + * @see java.lang.Class#getDeclaredMethods() + * @see java.lang.Class#getDeclaredMethod(String, Class[]) + * + * @author Kenneth Russell + * @author Nakul Saraiya + */ +public final + class Method extends AccessibleObject implements GenericDeclaration, + Member { + private final Class clazz; + private final String name; + private final Object data; + private final String sig; + private int modifiers; + + // Generics infrastructure + + private String getGenericSignature() {return null;} + + /** + * Package-private constructor used by ReflectAccess to enable + * instantiation of these objects in Java code from the java.lang + * package via sun.reflect.LangReflectAccess. + */ + Method(Class declaringClass, String name, Object data, String sig) + { + this.clazz = declaringClass; + this.name = name; + this.data = data; + this.sig = sig; + } + + /** + * Package-private routine (exposed to java.lang.Class via + * ReflectAccess) which returns a copy of this Method. The copy's + * "root" field points to this Method. + */ + Method copy() { + return this; + } + + /** + * Returns the {@code Class} object representing the class or interface + * that declares the method represented by this {@code Method} object. + */ + public Class getDeclaringClass() { + return clazz; + } + + /** + * Returns the name of the method represented by this {@code Method} + * object, as a {@code String}. + */ + public String getName() { + return name; + } + + /** + * Returns the Java language modifiers for the method represented + * by this {@code Method} object, as an integer. The {@code Modifier} class should + * be used to decode the modifiers. + * + * @see Modifier + */ + public int getModifiers() { + return modifiers; + } + + /** + * Returns an array of {@code TypeVariable} objects that represent the + * type variables declared by the generic declaration represented by this + * {@code GenericDeclaration} object, in declaration order. Returns an + * array of length 0 if the underlying generic declaration declares no type + * variables. + * + * @return an array of {@code TypeVariable} objects that represent + * the type variables declared by this generic declaration + * @throws GenericSignatureFormatError if the generic + * signature of this generic declaration does not conform to + * the format specified in + * The Java™ Virtual Machine Specification + * @since 1.5 + */ + public TypeVariable[] getTypeParameters() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a {@code Class} object that represents the formal return type + * of the method represented by this {@code Method} object. + * + * @return the return type for the method this object represents + */ + public Class getReturnType() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a {@code Type} object that represents the formal return + * type of the method represented by this {@code Method} object. + * + *

If the return type is a parameterized type, + * the {@code Type} object returned must accurately reflect + * the actual type parameters used in the source code. + * + *

If the return type is a type variable or a parameterized type, it + * is created. Otherwise, it is resolved. + * + * @return a {@code Type} object that represents the formal return + * type of the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * return type refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if the + * underlying method's return typed refers to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type getGenericReturnType() { + throw new UnsupportedOperationException(); + } + + + /** + * Returns an array of {@code Class} objects that represent the formal + * parameter types, in declaration order, of the method + * represented by this {@code Method} object. Returns an array of length + * 0 if the underlying method takes no parameters. + * + * @return the parameter types for the method this object + * represents + */ + public Class[] getParameterTypes() { + throw new UnsupportedOperationException(); + //return (Class[]) parameterTypes.clone(); + } + + /** + * Returns an array of {@code Type} objects that represent the formal + * parameter types, in declaration order, of the method represented by + * this {@code Method} object. Returns an array of length 0 if the + * underlying method takes no parameters. + * + *

If a formal parameter type is a parameterized type, + * the {@code Type} object returned for it must accurately reflect + * the actual type parameters used in the source code. + * + *

If a formal parameter type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the formal + * parameter types of the underlying method, in declaration order + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if any of the parameter + * types of the underlying method refers to a non-existent type + * declaration + * @throws MalformedParameterizedTypeException if any of + * the underlying method's parameter types refer to a parameterized + * type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericParameterTypes() { + throw new UnsupportedOperationException(); + } + + + /** + * Returns an array of {@code Class} objects that represent + * the types of the exceptions declared to be thrown + * by the underlying method + * represented by this {@code Method} object. Returns an array of length + * 0 if the method declares no exceptions in its {@code throws} clause. + * + * @return the exception types declared as being thrown by the + * method this object represents + */ + public Class[] getExceptionTypes() { + throw new UnsupportedOperationException(); + //return (Class[]) exceptionTypes.clone(); + } + + /** + * Returns an array of {@code Type} objects that represent the + * exceptions declared to be thrown by this {@code Method} object. + * Returns an array of length 0 if the underlying method declares + * no exceptions in its {@code throws} clause. + * + *

If an exception type is a type variable or a parameterized + * type, it is created. Otherwise, it is resolved. + * + * @return an array of Types that represent the exception types + * thrown by the underlying method + * @throws GenericSignatureFormatError + * if the generic method signature does not conform to the format + * specified in + * The Java™ Virtual Machine Specification + * @throws TypeNotPresentException if the underlying method's + * {@code throws} clause refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if + * the underlying method's {@code throws} clause refers to a + * parameterized type that cannot be instantiated for any reason + * @since 1.5 + */ + public Type[] getGenericExceptionTypes() { + throw new UnsupportedOperationException(); + } + + /** + * Compares this {@code Method} against the specified object. Returns + * true if the objects are the same. Two {@code Methods} are the same if + * they were declared by the same class and have the same name + * and formal parameter types and return type. + */ + public boolean equals(Object obj) { + if (obj != null && obj instanceof Method) { + Method other = (Method)obj; + return data == other.data; + } + return false; + } + + /** + * Returns a hashcode for this {@code Method}. The hashcode is computed + * as the exclusive-or of the hashcodes for the underlying + * method's declaring class name and the method's name. + */ + public int hashCode() { + return getDeclaringClass().getName().hashCode() ^ getName().hashCode(); + } + + /** + * Returns a string describing this {@code Method}. The string is + * formatted as the method access modifiers, if any, followed by + * the method return type, followed by a space, followed by the + * class declaring the method, followed by a period, followed by + * the method name, followed by a parenthesized, comma-separated + * list of the method's formal parameter types. If the method + * throws checked exceptions, the parameter list is followed by a + * space, followed by the word throws followed by a + * comma-separated list of the thrown exception types. + * For example: + *

+     *    public boolean java.lang.Object.equals(java.lang.Object)
+     * 
+ * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + */ + public String toString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & Modifier.methodModifiers(); + if (mod != 0) { + sb.append(Modifier.toString(mod)).append(' '); + } + sb.append(Field.getTypeName(getReturnType())).append(' '); + sb.append(Field.getTypeName(getDeclaringClass())).append('.'); + sb.append(getName()).append('('); + /* + Class[] params = parameterTypes; // avoid clone + for (int j = 0; j < params.length; j++) { + sb.append(Field.getTypeName(params[j])); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + Class[] exceptions = exceptionTypes; // avoid clone + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append(exceptions[k].getName()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + */ + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Returns a string describing this {@code Method}, including + * type parameters. The string is formatted as the method access + * modifiers, if any, followed by an angle-bracketed + * comma-separated list of the method's type parameters, if any, + * followed by the method's generic return type, followed by a + * space, followed by the class declaring the method, followed by + * a period, followed by the method name, followed by a + * parenthesized, comma-separated list of the method's generic + * formal parameter types. + * + * If this method was declared to take a variable number of + * arguments, instead of denoting the last parameter as + * "Type[]", it is denoted as + * "Type...". + * + * A space is used to separate access modifiers from one another + * and from the type parameters or return type. If there are no + * type parameters, the type parameter list is elided; if the type + * parameter list is present, a space separates the list from the + * class name. If the method is declared to throw exceptions, the + * parameter list is followed by a space, followed by the word + * throws followed by a comma-separated list of the generic thrown + * exception types. If there are no type parameters, the type + * parameter list is elided. + * + *

The access modifiers are placed in canonical order as + * specified by "The Java Language Specification". This is + * {@code public}, {@code protected} or {@code private} first, + * and then other modifiers in the following order: + * {@code abstract}, {@code static}, {@code final}, + * {@code synchronized}, {@code native}, {@code strictfp}. + * + * @return a string describing this {@code Method}, + * include type parameters + * + * @since 1.5 + */ + public String toGenericString() { + try { + StringBuilder sb = new StringBuilder(); + int mod = getModifiers() & Modifier.methodModifiers(); + if (mod != 0) { + sb.append(Modifier.toString(mod)).append(' '); + } + TypeVariable[] typeparms = getTypeParameters(); + if (typeparms.length > 0) { + boolean first = true; + sb.append('<'); + for(TypeVariable typeparm: typeparms) { + if (!first) + sb.append(','); + // Class objects can't occur here; no need to test + // and call Class.getName(). + sb.append(typeparm.toString()); + first = false; + } + sb.append("> "); + } + + Type genRetType = getGenericReturnType(); + sb.append( ((genRetType instanceof Class)? + Field.getTypeName((Class)genRetType):genRetType.toString())) + .append(' '); + + sb.append(Field.getTypeName(getDeclaringClass())).append('.'); + sb.append(getName()).append('('); + Type[] params = getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) { + String param = (params[j] instanceof Class)? + Field.getTypeName((Class)params[j]): + (params[j].toString()); + if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... + param = param.replaceFirst("\\[\\]$", "..."); + sb.append(param); + if (j < (params.length - 1)) + sb.append(','); + } + sb.append(')'); + Type[] exceptions = getGenericExceptionTypes(); + if (exceptions.length > 0) { + sb.append(" throws "); + for (int k = 0; k < exceptions.length; k++) { + sb.append((exceptions[k] instanceof Class)? + ((Class)exceptions[k]).getName(): + exceptions[k].toString()); + if (k < (exceptions.length - 1)) + sb.append(','); + } + } + return sb.toString(); + } catch (Exception e) { + return "<" + e + ">"; + } + } + + /** + * Invokes the underlying method represented by this {@code Method} + * object, on the specified object with the specified parameters. + * Individual parameters are automatically unwrapped to match + * primitive formal parameters, and both primitive and reference + * parameters are subject to method invocation conversions as + * necessary. + * + *

If the underlying method is static, then the specified {@code obj} + * argument is ignored. It may be null. + * + *

If the number of formal parameters required by the underlying method is + * 0, the supplied {@code args} array may be of length 0 or null. + * + *

If the underlying method is an instance method, it is invoked + * using dynamic method lookup as documented in The Java Language + * Specification, Second Edition, section 15.12.4.4; in particular, + * overriding based on the runtime type of the target object will occur. + * + *

If the underlying method is static, the class that declared + * the method is initialized if it has not already been initialized. + * + *

If the method completes normally, the value it returns is + * returned to the caller of invoke; if the value has a primitive + * type, it is first appropriately wrapped in an object. However, + * if the value has the type of an array of a primitive type, the + * elements of the array are not wrapped in objects; in + * other words, an array of primitive type is returned. If the + * underlying method return type is void, the invocation returns + * null. + * + * @param obj the object the underlying method is invoked from + * @param args the arguments used for the method call + * @return the result of dispatching the method represented by + * this object on {@code obj} with parameters + * {@code args} + * + * @exception IllegalAccessException if this {@code Method} object + * is enforcing Java language access control and the underlying + * method is inaccessible. + * @exception IllegalArgumentException if the method is an + * instance method and the specified object argument + * is not an instance of the class or interface + * declaring the underlying method (or of a subclass + * or implementor thereof); if the number of actual + * and formal parameters differ; if an unwrapping + * conversion for primitive arguments fails; or if, + * after possible unwrapping, a parameter value + * cannot be converted to the corresponding formal + * parameter type by a method invocation conversion. + * @exception InvocationTargetException if the underlying method + * throws an exception. + * @exception NullPointerException if the specified object is null + * and the method is an instance method. + * @exception ExceptionInInitializerError if the initialization + * provoked by this method fails. + */ + @JavaScriptBody(args = { "method", "self", "args" }, body = + "if (args.length > 0) throw 'unsupported now';" + + "return method.fld_data(self);" + ) + public Object invoke(Object obj, Object... args) + throws IllegalAccessException, IllegalArgumentException, + InvocationTargetException + { + throw new UnsupportedOperationException(); + } + + /** + * Returns {@code true} if this method is a bridge + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a bridge + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isBridge() { + return (getModifiers() & Modifier.BRIDGE) != 0; + } + + /** + * Returns {@code true} if this method was declared to take + * a variable number of arguments; returns {@code false} + * otherwise. + * + * @return {@code true} if an only if this method was declared to + * take a variable number of arguments. + * @since 1.5 + */ + public boolean isVarArgs() { + return (getModifiers() & Modifier.VARARGS) != 0; + } + + /** + * Returns {@code true} if this method is a synthetic + * method; returns {@code false} otherwise. + * + * @return true if and only if this method is a synthetic + * method as defined by the Java Language Specification. + * @since 1.5 + */ + public boolean isSynthetic() { + return Modifier.isSynthetic(getModifiers()); + } + + @JavaScriptBody(args = { "self", "ac" }, + body = + "if (self.fld_data.anno) {" + + " return self.fld_data.anno['L' + ac.jvmName + ';'];" + + "} else return null;" + ) + private Object getAnnotationData(Class annotationClass) { + throw new UnsupportedOperationException(); + } + + /** + * @throws NullPointerException {@inheritDoc} + * @since 1.5 + */ + public T getAnnotation(Class annotationClass) { + Object data = getAnnotationData(annotationClass); + return data == null ? null : AnnotationImpl.create(annotationClass, data); + } + + /** + * @since 1.5 + */ + public Annotation[] getDeclaredAnnotations() { + throw new UnsupportedOperationException(); + } + + /** + * Returns the default value for the annotation member represented by + * this {@code Method} instance. If the member is of a primitive type, + * an instance of the corresponding wrapper type is returned. Returns + * null if no default is associated with the member, or if the method + * instance does not represent a declared member of an annotation type. + * + * @return the default value for the annotation member represented + * by this {@code Method} instance. + * @throws TypeNotPresentException if the annotation is of type + * {@link Class} and no definition can be found for the + * default class value. + * @since 1.5 + */ + public Object getDefaultValue() { + throw new UnsupportedOperationException(); + } + + /** + * Returns an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by + * this {@code Method} object. (Returns an array of length zero if the + * underlying method is parameterless. If the method has one or more + * parameters, a nested array of length zero is returned for each parameter + * with no annotations.) The annotation objects contained in the returned + * arrays are serializable. The caller of this method is free to modify + * the returned arrays; it will have no effect on the arrays returned to + * other callers. + * + * @return an array of arrays that represent the annotations on the formal + * parameters, in declaration order, of the method represented by this + * Method object + * @since 1.5 + */ + public Annotation[][] getParameterAnnotations() { + throw new UnsupportedOperationException(); + } + + // + // bck2brwsr implementation + // + + @JavaScriptBody(args = { "clazz", "prefix" }, + body = "" + + "var c = clazz.cnstr.prototype;" + + "var arr = new Array();\n" + + "for (m in c) {\n" + + " if (m.indexOf(prefix) === 0) {\n" + + " arr.push(m);\n" + + " arr.push(c[m]);\n" + + " }" + + "}\n" + + "return arr;" + ) + private static native Object[] findMethodData( + Class clazz, String prefix + ); + + // XXX should not be public + public static Method findMethod( + Class clazz, String name, Class... parameterTypes + ) { + Object[] data = findMethodData(clazz, name + "__"); + if (data.length == 0) { + return null; + } + String sig = ((String)data[0]).substring(name.length() + 2); + return new Method(clazz, name, data[1], sig); + } + + public static Method[] findMethods(Class clazz) { + Object[] namesAndData = findMethodData(clazz, ""); + int cnt = 0; + for (int i = 0; i < namesAndData.length; i += 2) { + String sig = (String) namesAndData[i]; + Object data = namesAndData[i + 1]; + int middle = sig.indexOf("__"); + if (middle == -1) { + continue; + } + String name = sig.substring(0, middle); + sig = sig.substring(middle + 2); + namesAndData[cnt++] = new Method(clazz, name, data, sig); + } + Method[] arr = new Method[cnt]; + for (int i = 0; i < cnt; i++) { + arr[i] = (Method)namesAndData[i]; + } + return arr; + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/Modifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Modifier.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * The Modifier class provides {@code static} methods and + * constants to decode class and member access modifiers. The sets of + * modifiers are represented as integers with distinct bit positions + * representing different modifiers. The values for the constants + * representing the modifiers are taken from the tables in sections 4.1, 4.4, 4.5, and 4.7 of + * The Java™ Virtual Machine Specification. + * + * @see Class#getModifiers() + * @see Member#getModifiers() + * + * @author Nakul Saraiya + * @author Kenneth Russell + */ +public +class Modifier { + + /** + * Return {@code true} if the integer argument includes the + * {@code public} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code public} modifier; {@code false} otherwise. + */ + public static boolean isPublic(int mod) { + return (mod & PUBLIC) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code private} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code private} modifier; {@code false} otherwise. + */ + public static boolean isPrivate(int mod) { + return (mod & PRIVATE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code protected} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code protected} modifier; {@code false} otherwise. + */ + public static boolean isProtected(int mod) { + return (mod & PROTECTED) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code static} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code static} modifier; {@code false} otherwise. + */ + public static boolean isStatic(int mod) { + return (mod & STATIC) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code final} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code final} modifier; {@code false} otherwise. + */ + public static boolean isFinal(int mod) { + return (mod & FINAL) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code synchronized} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code synchronized} modifier; {@code false} otherwise. + */ + public static boolean isSynchronized(int mod) { + return (mod & SYNCHRONIZED) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code volatile} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code volatile} modifier; {@code false} otherwise. + */ + public static boolean isVolatile(int mod) { + return (mod & VOLATILE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code transient} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code transient} modifier; {@code false} otherwise. + */ + public static boolean isTransient(int mod) { + return (mod & TRANSIENT) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code native} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code native} modifier; {@code false} otherwise. + */ + public static boolean isNative(int mod) { + return (mod & NATIVE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code interface} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code interface} modifier; {@code false} otherwise. + */ + public static boolean isInterface(int mod) { + return (mod & INTERFACE) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code abstract} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code abstract} modifier; {@code false} otherwise. + */ + public static boolean isAbstract(int mod) { + return (mod & ABSTRACT) != 0; + } + + /** + * Return {@code true} if the integer argument includes the + * {@code strictfp} modifier, {@code false} otherwise. + * + * @param mod a set of modifiers + * @return {@code true} if {@code mod} includes the + * {@code strictfp} modifier; {@code false} otherwise. + */ + public static boolean isStrict(int mod) { + return (mod & STRICT) != 0; + } + + /** + * Return a string describing the access modifier flags in + * the specified modifier. For example: + *

+     *    public final synchronized strictfp
+     * 
+ * The modifier names are returned in an order consistent with the + * suggested modifier orderings given in sections 8.1.1, 8.3.1, 8.4.3, 8.8.3, and 9.1.1 of + * The Java™ Language Specification. + * The full modifier ordering used by this method is: + *
{@code + * public protected private abstract static final transient + * volatile synchronized native strictfp + * interface }
+ * The {@code interface} modifier discussed in this class is + * not a true modifier in the Java language and it appears after + * all other modifiers listed by this method. This method may + * return a string of modifiers that are not valid modifiers of a + * Java entity; in other words, no checking is done on the + * possible validity of the combination of modifiers represented + * by the input. + * + * Note that to perform such checking for a known kind of entity, + * such as a constructor or method, first AND the argument of + * {@code toString} with the appropriate mask from a method like + * {@link #constructorModifiers} or {@link #methodModifiers}. + * + * @param mod a set of modifiers + * @return a string representation of the set of modifiers + * represented by {@code mod} + */ + public static String toString(int mod) { + StringBuffer sb = new StringBuffer(); + int len; + + if ((mod & PUBLIC) != 0) sb.append("public "); + if ((mod & PROTECTED) != 0) sb.append("protected "); + if ((mod & PRIVATE) != 0) sb.append("private "); + + /* Canonical order */ + if ((mod & ABSTRACT) != 0) sb.append("abstract "); + if ((mod & STATIC) != 0) sb.append("static "); + if ((mod & FINAL) != 0) sb.append("final "); + if ((mod & TRANSIENT) != 0) sb.append("transient "); + if ((mod & VOLATILE) != 0) sb.append("volatile "); + if ((mod & SYNCHRONIZED) != 0) sb.append("synchronized "); + if ((mod & NATIVE) != 0) sb.append("native "); + if ((mod & STRICT) != 0) sb.append("strictfp "); + if ((mod & INTERFACE) != 0) sb.append("interface "); + + if ((len = sb.length()) > 0) /* trim trailing space */ + return sb.toString().substring(0, len-1); + return ""; + } + + /* + * Access modifier flag constants from tables 4.1, 4.4, 4.5, and 4.7 of + * The Java™ Virtual Machine Specification + */ + + /** + * The {@code int} value representing the {@code public} + * modifier. + */ + public static final int PUBLIC = 0x00000001; + + /** + * The {@code int} value representing the {@code private} + * modifier. + */ + public static final int PRIVATE = 0x00000002; + + /** + * The {@code int} value representing the {@code protected} + * modifier. + */ + public static final int PROTECTED = 0x00000004; + + /** + * The {@code int} value representing the {@code static} + * modifier. + */ + public static final int STATIC = 0x00000008; + + /** + * The {@code int} value representing the {@code final} + * modifier. + */ + public static final int FINAL = 0x00000010; + + /** + * The {@code int} value representing the {@code synchronized} + * modifier. + */ + public static final int SYNCHRONIZED = 0x00000020; + + /** + * The {@code int} value representing the {@code volatile} + * modifier. + */ + public static final int VOLATILE = 0x00000040; + + /** + * The {@code int} value representing the {@code transient} + * modifier. + */ + public static final int TRANSIENT = 0x00000080; + + /** + * The {@code int} value representing the {@code native} + * modifier. + */ + public static final int NATIVE = 0x00000100; + + /** + * The {@code int} value representing the {@code interface} + * modifier. + */ + public static final int INTERFACE = 0x00000200; + + /** + * The {@code int} value representing the {@code abstract} + * modifier. + */ + public static final int ABSTRACT = 0x00000400; + + /** + * The {@code int} value representing the {@code strictfp} + * modifier. + */ + public static final int STRICT = 0x00000800; + + // Bits not (yet) exposed in the public API either because they + // have different meanings for fields and methods and there is no + // way to distinguish between the two in this class, or because + // they are not Java programming language keywords + static final int BRIDGE = 0x00000040; + static final int VARARGS = 0x00000080; + static final int SYNTHETIC = 0x00001000; + static final int ANNOTATION= 0x00002000; + static final int ENUM = 0x00004000; + static boolean isSynthetic(int mod) { + return (mod & SYNTHETIC) != 0; + } + + /** + * See JLSv3 section 8.1.1. + */ + private static final int CLASS_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | + Modifier.STRICT; + + /** + * See JLSv3 section 9.1.1. + */ + private static final int INTERFACE_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.STRICT; + + + /** + * See JLSv3 section 8.8.3. + */ + private static final int CONSTRUCTOR_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE; + + /** + * See JLSv3 section 8.4.3. + */ + private static final int METHOD_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.ABSTRACT | Modifier.STATIC | Modifier.FINAL | + Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.STRICT; + + /** + * See JLSv3 section 8.3.1. + */ + private static final int FIELD_MODIFIERS = + Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE | + Modifier.STATIC | Modifier.FINAL | Modifier.TRANSIENT | + Modifier.VOLATILE; + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a class. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a class. + * + * @jls 8.1.1 Class Modifiers + * @since 1.7 + */ + public static int classModifiers() { + return CLASS_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to an interface. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to an inteface. + * + * @jls 9.1.1 Interface Modifiers + * @since 1.7 + */ + public static int interfaceModifiers() { + return INTERFACE_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a constructor. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a constructor. + * + * @jls 8.8.3 Constructor Modifiers + * @since 1.7 + */ + public static int constructorModifiers() { + return CONSTRUCTOR_MODIFIERS; + } + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a method. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a method. + * + * @jls 8.4.3 Method Modifiers + * @since 1.7 + */ + public static int methodModifiers() { + return METHOD_MODIFIERS; + } + + + /** + * Return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a field. + * @return an {@code int} value OR-ing together the source language + * modifiers that can be applied to a field. + * + * @jls 8.3.1 Field Modifiers + * @since 1.7 + */ + public static int fieldModifiers() { + return FIELD_MODIFIERS; + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/Type.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/Type.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * Type is the common superinterface for all types in the Java + * programming language. These include raw types, parameterized types, + * array types, type variables and primitive types. + * + * @since 1.5 + */ + +public interface Type { +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/TypeVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/TypeVariable.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.reflect; + +/** + * TypeVariable is the common superinterface for type variables of kinds. + * A type variable is created the first time it is needed by a reflective + * method, as specified in this package. If a type variable t is referenced + * by a type (i.e, class, interface or annotation type) T, and T is declared + * by the nth enclosing class of T (see JLS 8.1.2), then the creation of t + * requires the resolution (see JVMS 5) of the ith enclosing class of T, + * for i = 0 to n, inclusive. Creating a type variable must not cause the + * creation of its bounds. Repeated creation of a type variable has no effect. + * + *

Multiple objects may be instantiated at run-time to + * represent a given type variable. Even though a type variable is + * created only once, this does not imply any requirement to cache + * instances representing the type variable. However, all instances + * representing a type variable must be equal() to each other. + * As a consequence, users of type variables must not rely on the identity + * of instances of classes implementing this interface. + * + * @param the type of generic declaration that declared the + * underlying type variable. + * + * @since 1.5 + */ +public interface TypeVariable extends Type { + /** + * Returns an array of {@code Type} objects representing the + * upper bound(s) of this type variable. Note that if no upper bound is + * explicitly declared, the upper bound is {@code Object}. + * + *

For each upper bound B:

  • if B is a parameterized + * type or a type variable, it is created, (see {@link + * java.lang.reflect.ParameterizedType ParameterizedType} for the + * details of the creation process for parameterized types). + *
  • Otherwise, B is resolved.
+ * + * @throws TypeNotPresentException if any of the + * bounds refers to a non-existent type declaration + * @throws MalformedParameterizedTypeException if any of the + * bounds refer to a parameterized type that cannot be instantiated + * for any reason + * @return an array of {@code Type}s representing the upper + * bound(s) of this type variable + */ + Type[] getBounds(); + + /** + * Returns the {@code GenericDeclaration} object representing the + * generic declaration declared this type variable. + * + * @return the generic declaration declared for this type variable. + * + * @since 1.5 + */ + D getGenericDeclaration(); + + /** + * Returns the name of this type variable, as it occurs in the source code. + * + * @return the name of this type variable, as it appears in the source code + */ + String getName(); +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/java/lang/reflect/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/java/lang/reflect/package-info.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Provides classes and interfaces for obtaining reflective + * information about classes and objects. Reflection allows + * programmatic access to information about the fields, methods and + * constructors of loaded classes, and the use of reflected fields, + * methods, and constructors to operate on their underlying + * counterparts, within security restrictions. + * + *

{@code AccessibleObject} allows suppression of access checks if + * the necessary {@code ReflectPermission} is available. + * + *

{@code Array} provides static methods to dynamically create and + * access arrays. + * + *

Classes in this package, along with {@code java.lang.Class} + * accommodate applications such as debuggers, interpreters, object + * inspectors, class browsers, and services such as Object + * Serialization and JavaBeans that need access to either the public + * members of a target object (based on its runtime class) or the + * members declared by a given class. + * + * @since JDK1.1 + */ +package java.lang.reflect; diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,68 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.apidesign.bck2brwsr.emul; + +import java.lang.annotation.Annotation; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +public final class AnnotationImpl implements Annotation { + public Class annotationType() { + return getClass(); + } + + @JavaScriptBody(args = { "a", "n", "values" }, body = "" + + "function f(v, p) {\n" + + " var val = v;\n" + + " var prop = p;\n" + + " return function() {\n" + + " return val[prop];\n" + + " };\n" + + "}\n" + + "var props = Object.getOwnPropertyNames(values);\n" + + "for (var i = 0; i < props.length; i++) {\n" + + " var p = props[i];\n" + + " a[p] = new f(values, p);\n" + + "}\n" + + "a['$instOf_' + n] = true;\n" + + "return a;" + ) + private static T create(AnnotationImpl a, String n, Object values) { + return null; + } + public static T create(Class annoClass, Object values) { + return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values); + } + + public static Annotation[] create(Object anno) { + String[] names = findNames(anno); + Annotation[] ret = new Annotation[names.length]; + for (int i = 0; i < names.length; i++) { + String n = names[i].substring(1, names[i].length() - 1).replace('/', '_'); + ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i])); + } + return ret; + } + @JavaScriptBody(args = "anno", body = + "var arr = new Array();" + + "var props = Object.getOwnPropertyNames(anno);\n" + + "for (var i = 0; i < props.length; i++) {\n" + + " var p = props[i];\n" + + " arr.push(p);" + + "}" + + "return arr;" + ) + private static String[] findNames(Object anno) { + throw new UnsupportedOperationException(); + } + + @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];") + private static Object findData(Object anno, String p) { + throw new UnsupportedOperationException(); + } +} diff -r 0bfcb6585290 -r 79697fa91bfc emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js --- a/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Tue Dec 04 09:16:53 2012 +0100 +++ b/emul/src/main/resources/org/apidesign/vm4brwsr/emul/java_lang_String.js Wed Dec 05 10:52:50 2012 +0100 @@ -1,2 +1,2 @@ // initialize methods on String constants -java_lang_String(false) +java_lang_String(false); diff -r 0bfcb6585290 -r 79697fa91bfc javap/src/main/java/org/apidesign/javap/AnnotationParser.java --- a/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Tue Dec 04 09:16:53 2012 +0100 +++ b/javap/src/main/java/org/apidesign/javap/AnnotationParser.java Wed Dec 05 10:52:50 2012 +0100 @@ -34,10 +34,21 @@ * @author Jaroslav Tulach */ public class AnnotationParser { - protected AnnotationParser() { + private final boolean textual; + + protected AnnotationParser(boolean textual) { + this.textual = textual; } - protected void visitAttr(String type, String attr, String value) { + protected void visitAnnotationStart(String type) throws IOException { + } + + protected void visitAnnotationEnd(String type) throws IOException { + } + + protected void visitAttr( + String annoType, String attr, String attrType, String value + ) throws IOException { } /** Initialize the parsing with constant pool from cd. @@ -66,13 +77,15 @@ private void readAnno(DataInputStream dis, ClassData cd) throws IOException { int type = dis.readUnsignedShort(); String typeName = cd.StringValue(type); + visitAnnotationStart(typeName); int cnt = dis.readUnsignedShort(); for (int i = 0; i < cnt; i++) { String attrName = cd.StringValue(dis.readUnsignedShort()); readValue(dis, cd, typeName, attrName); } + visitAnnotationEnd(typeName); if (cnt == 0) { - visitAttr(typeName, null, null); + visitAttr(typeName, null, null, null); } } @@ -83,7 +96,17 @@ readAnno(dis, cd); } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N int primitive = dis.readUnsignedShort(); - visitAttr(typeName, attrName, cd.StringValue(primitive)); + String val = cd.stringValue(primitive, textual); + String attrType; + if (type == 's') { + attrType = "Ljava_lang_String_2"; + if (textual) { + val = '"' + val + '"'; + } + } else { + attrType = "" + type; + } + visitAttr(typeName, attrName, attrType, val); } else if (type == 'c') { int cls = dis.readUnsignedShort(); } else if (type == '[') { diff -r 0bfcb6585290 -r 79697fa91bfc javap/src/main/java/org/apidesign/javap/ClassData.java --- a/javap/src/main/java/org/apidesign/javap/ClassData.java Tue Dec 04 09:16:53 2012 +0100 +++ b/javap/src/main/java/org/apidesign/javap/ClassData.java Wed Dec 05 10:52:50 2012 +0100 @@ -488,6 +488,12 @@ return stringValue(cpx, false); } public String stringValue(int cpx, boolean textual) { + return stringValue(cpx, textual, null); + } + public String stringValue(int cpx, String[] classRefs) { + return stringValue(cpx, true, classRefs); + } + private String stringValue(int cpx, boolean textual, String[] refs) { if (cpx==0) return "#0"; int tag; Object x; @@ -548,10 +554,14 @@ return in.toString(); } case CONSTANT_CLASS: + String jn = javaName(getClassName(cpx)); if (textual) { - return "new java_lang_Class"; // XXX temporary JS + if (refs != null) { + refs[0] = jn; + } + return jn.replace('/', '_') + "(false).constructor.$class"; } - return javaName(getClassName(cpx)); + return jn; case CONSTANT_STRING: String sv = stringValue(((CPX)x).cpx, textual); if (textual) { diff -r 0bfcb6585290 -r 79697fa91bfc javap/src/main/java/org/apidesign/javap/FieldData.java --- a/javap/src/main/java/org/apidesign/javap/FieldData.java Tue Dec 04 09:16:53 2012 +0100 +++ b/javap/src/main/java/org/apidesign/javap/FieldData.java Wed Dec 05 10:52:50 2012 +0100 @@ -130,13 +130,6 @@ } /** - * Returns java type signature of a field. - */ - public String getType(){ - return new TypeSignature(getInternalSig()).getFieldType(); - } - - /** * Returns true if field is synthetic. */ public boolean isSynthetic(){ diff -r 0bfcb6585290 -r 79697fa91bfc javap/src/main/java/org/apidesign/javap/MethodData.java --- a/javap/src/main/java/org/apidesign/javap/MethodData.java Tue Dec 04 09:16:53 2012 +0100 +++ b/javap/src/main/java/org/apidesign/javap/MethodData.java Wed Dec 05 10:52:50 2012 +0100 @@ -268,24 +268,6 @@ } /** - * Return java return type signature of method. - */ - public String getReturnType(){ - - String rttype = (new TypeSignature(getInternalSig())).getReturnType(); - return rttype; - } - - /** - * Return java type parameter signature. - */ - public String getParameters(){ - String ptype = (new TypeSignature(getInternalSig())).getParameters(); - - return ptype; - } - - /** * Return code attribute data of a method. */ public byte[] getCode(){ @@ -336,13 +318,6 @@ } /** - * Return number of arguments of that method. - */ - public int getArgumentlength(){ - return new TypeSignature(getInternalSig()).getArgumentlength(); - } - - /** * Return true if method is static */ public boolean isStatic(){ diff -r 0bfcb6585290 -r 79697fa91bfc javap/src/main/java/org/apidesign/javap/TypeSignature.java --- a/javap/src/main/java/org/apidesign/javap/TypeSignature.java Tue Dec 04 09:16:53 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -package org.apidesign.javap; - -import java.util.*; -import java.io.*; - -/** - * Returns java type signature. - * - * @author Sucheta Dambalkar - */ -public class TypeSignature { - - String parameters = null; - String returntype = null; - String fieldtype = null; - int argumentlength = 0; - - public TypeSignature(String JVMSignature){ - - if(JVMSignature != null){ - if(JVMSignature.indexOf("(") == -1){ - //This is a field type. - this.fieldtype = getFieldTypeSignature(JVMSignature); - }else { - String parameterdes = null; - if((JVMSignature.indexOf(")")-1) > (JVMSignature.indexOf("("))){ - //Get parameter signature. - parameterdes = - JVMSignature.substring(JVMSignature.indexOf("(")+1, - JVMSignature.indexOf(")")); - this.parameters = getParametersHelper(parameterdes); - }else this.parameters = "()"; - //Get return type signature. - String returndes = JVMSignature.substring(JVMSignature.lastIndexOf(")")+1); - this.returntype = getReturnTypeHelper(returndes); - } - } - } - - /** - * Returns java type signature of a field. - */ - public String getFieldTypeSignature(String fielddes){ - if(fielddes.startsWith("L")){ - return(getObjectType(fielddes)); - }else if(fielddes.startsWith("[")){ - return(getArrayType(fielddes)); - }else - return(getBaseType(fielddes)); - } - - /** - * Returns java type signature of a parameter. - */ - public String getParametersHelper(String parameterdes){ - Vector parameters = new Vector(); - int startindex = -1; - int endindex = -1; - String param = ""; - - while(parameterdes != null){ - - if(parameterdes.startsWith("L")){ - //parameter is a object. - startindex = parameterdes.indexOf("L"); - endindex = parameterdes.indexOf(";"); - if(startindex < parameterdes.length()) { - if(endindex == parameterdes.length()-1) { - //last parameter - param = parameterdes.substring(startindex); - parameterdes = null; - }else if(endindex+1 < parameterdes.length()){ - //rest parameters - param = parameterdes.substring(startindex, endindex+1); - parameterdes = parameterdes.substring(endindex+1); - - } - parameters.add(getObjectType(param)); - } - }else if(parameterdes.startsWith("[")){ - //parameter is an array. - String componentType = ""; - int enddim = -1; - int st = 0; - while(true){ - if(st < parameterdes.length()){ - if(parameterdes.charAt(st) == '['){ - - enddim = st; - st++; - } - else break; - } - else break; - } - - if(enddim+1 < parameterdes.length()){ - /* Array dimension.*/ - param = parameterdes.substring(0,enddim+1); - - } - - int stotherparam = param.lastIndexOf("[")+1; - - if(stotherparam < parameterdes.length()){ - componentType = parameterdes.substring(stotherparam); - } - - if(componentType.startsWith("L")){ - //parameter is array of objects. - startindex = parameterdes.indexOf("L"); - endindex = parameterdes.indexOf(";"); - - if(endindex == parameterdes.length()-1){ - //last parameter - param += parameterdes.substring(startindex); - parameterdes = null; - }else if(endindex+1 < parameterdes.length()){ - //rest parameters - param += parameterdes.substring(startindex, endindex+1); - parameterdes = parameterdes.substring(endindex+1); - } - }else{ - //parameter is array of base type. - if(componentType.length() == 1){ - //last parameter. - param += componentType; - parameterdes = null; - } - else if (componentType.length() > 1) { - //rest parameters. - param += componentType.substring(0,1); - parameterdes = componentType.substring(1); - } - } - parameters.add(getArrayType(param)); - - - }else { - - //parameter is of base type. - if(parameterdes.length() == 1){ - //last parameter - param = parameterdes; - parameterdes = null; - } - else if (parameterdes.length() > 1) { - //rest parameters. - param = parameterdes.substring(0,1); - parameterdes = parameterdes.substring(1); - } - parameters.add(getBaseType(param)); - } - } - - /* number of arguments of a method.*/ - argumentlength = parameters.size(); - - /* java type signature.*/ - String parametersignature = "("; - int i; - - for(i = 0; i < parameters.size(); i++){ - parametersignature += (String)parameters.elementAt(i); - if(i != parameters.size()-1){ - parametersignature += ", "; - } - } - parametersignature += ")"; - return parametersignature; - } - - /** - * Returns java type signature for a return type. - */ - public String getReturnTypeHelper(String returndes){ - return getFieldTypeSignature(returndes); - } - - /** - * Returns java type signature for a base type. - */ - public String getBaseType(String baseType){ - if(baseType != null){ - if(baseType.equals("B")) return "byte"; - else if(baseType.equals("C")) return "char"; - else if(baseType.equals("D")) return "double"; - else if(baseType.equals("F")) return "float"; - else if(baseType.equals("I")) return "int"; - else if(baseType.equals("J")) return "long"; - else if(baseType.equals("S")) return "short"; - else if(baseType.equals("Z")) return "boolean"; - else if(baseType.equals("V")) return "void"; - } - return null; - } - - /** - * Returns java type signature for a object type. - */ - public String getObjectType(String JVMobjectType) { - String objectType = ""; - int startindex = JVMobjectType.indexOf("L")+1; - int endindex = JVMobjectType.indexOf(";"); - if((startindex != -1) && (endindex != -1)){ - if((startindex < JVMobjectType.length()) && (endindex < JVMobjectType.length())){ - objectType = JVMobjectType.substring(startindex, endindex); - } - objectType = objectType.replace('/','.'); - return objectType; - } - return null; - } - - /** - * Returns java type signature for array type. - */ - public String getArrayType(String arrayType) { - if(arrayType != null){ - String dimention = ""; - - while(arrayType.indexOf("[") != -1){ - dimention += "[]"; - - int startindex = arrayType.indexOf("[")+1; - if(startindex <= arrayType.length()){ - arrayType = arrayType.substring(startindex); - } - } - - String componentType = ""; - if(arrayType.startsWith("L")){ - componentType = getObjectType(arrayType); - }else { - componentType = getBaseType(arrayType); - } - return componentType+dimention; - } - return null; - } - - /** - * Returns java type signature for parameters. - */ - public String getParameters(){ - return parameters; - } - - /** - * Returns java type signature for return type. - */ - public String getReturnType(){ - return returntype; - } - - /** - * Returns java type signature for field type. - */ - public String getFieldType(){ - return fieldtype; - } - - /** - * Return number of arguments of a method. - */ - public int getArgumentlength(){ - return argumentlength; - } -} diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Tue Dec 04 09:16:53 2012 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Dec 05 10:52:50 2012 +0100 @@ -98,12 +98,15 @@ } if (proto == null) { String sc = jc.getSuperClassName(); // with _ - out.append("\n var p = CLS.prototype = "). + out.append("\n var pp = "). append(sc.replace('/', '_')).append("(true);"); + out.append("\n var p = CLS.prototype = pp;"); out.append("\n var c = p;"); + out.append("\n var sprcls = pp.constructor.$class;"); } else { out.append("\n var p = CLS.prototype = ").append(proto[1]).append(";"); out.append("\n var c = ").append(proto[0]).append(";"); + out.append("\n var sprcls = null;"); } for (MethodData m : jc.getMethods()) { byte[] onlyArr = m.findAnnotationData(true); @@ -118,10 +121,17 @@ } continue; } + String mn; if (m.isStatic()) { - generateStaticMethod("\n c.", m, toInitilize); + mn = generateStaticMethod("\n c.", m, toInitilize); } else { - generateInstanceMethod("\n c.", m); + mn = generateInstanceMethod("\n c.", m); + } + byte[] runAnno = m.findAnnotationData(false); + if (runAnno != null) { + out.append("\n c.").append(mn).append(".anno = {"); + generateAnno(jc, out, runAnno); + out.append("\n };"); } } out.append("\n c.constructor = CLS;"); @@ -129,6 +139,16 @@ for (String superInterface : jc.getSuperInterfaces()) { out.append("\n c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;"); } + out.append("\n CLS.$class = java_lang_Class(true);"); + out.append("\n CLS.$class.jvmName = '").append(jc.getClassName()).append("';"); + out.append("\n CLS.$class.superclass = sprcls;"); + out.append("\n CLS.$class.cnstr = CLS;"); + byte[] classAnno = jc.findAnnotationData(false); + if (classAnno != null) { + out.append("\n CLS.$class.anno = {"); + generateAnno(jc, out, classAnno); + out.append("\n };"); + } out.append("\n }"); out.append("\n if (arguments.length === 0) {"); out.append("\n if (!(this instanceof CLS)) {"); @@ -162,9 +182,10 @@ } return sb.toString(); } - private void generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException { - if (javaScriptBody(prefix, m, true)) { - return; + private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException { + String jsb = javaScriptBody(prefix, m, true); + if (jsb != null) { + return jsb; } StringBuilder argsCnt = new StringBuilder(); final String mn = findMethodName(m, argsCnt); @@ -199,11 +220,13 @@ out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n"); } out.append("};"); + return mn; } - private void generateInstanceMethod(String prefix, MethodData m) throws IOException { - if (javaScriptBody(prefix, m, false)) { - return; + private String generateInstanceMethod(String prefix, MethodData m) throws IOException { + String jsb = javaScriptBody(prefix, m, false); + if (jsb != null) { + return jsb; } StringBuilder argsCnt = new StringBuilder(); final String mn = findMethodName(m, argsCnt); @@ -233,6 +256,7 @@ out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n"); } out.append("};"); + return mn; } private void produceCode(byte[] byteCodes) throws IOException { @@ -1002,24 +1026,32 @@ } } - private String encodeConstant(int entryIndex) { - String s = jc.stringValue(entryIndex, true); + private String encodeConstant(int entryIndex) throws IOException { + String[] classRef = { null }; + String s = jc.stringValue(entryIndex, classRef); + if (classRef[0] != null) { + addReference(classRef[0]); + } return s; } - private boolean javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException { + private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException { byte[] arr = m.findAnnotationData(true); if (arr == null) { - return false; + return null; } final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;"; class P extends AnnotationParser { + public P() { + super(false); + } + int cnt; String[] args = new String[30]; String body; @Override - protected void visitAttr(String type, String attr, String value) { + protected void visitAttr(String type, String attr, String at, String value) { if (type.equals(jvmType)) { if ("body".equals(attr)) { body = value; @@ -1034,10 +1066,11 @@ P p = new P(); p.parse(arr, jc); if (p.body == null) { - return false; + return null; } StringBuilder cnt = new StringBuilder(); - out.append(prefix).append(findMethodName(m, cnt)); + final String mn = findMethodName(m, cnt); + out.append(prefix).append(mn); out.append(" = function("); String space; int index; @@ -1058,7 +1091,7 @@ out.append(") {").append("\n"); out.append(p.body); out.append("\n}\n"); - return true; + return mn; } private static String className(ClassData jc) { //return jc.getName().getInternalName().replace('/', '_'); @@ -1075,9 +1108,9 @@ final String[] values = new String[attrNames.length]; final boolean[] found = { false }; final String jvmType = "L" + className.replace('.', '/') + ";"; - AnnotationParser ap = new AnnotationParser() { + AnnotationParser ap = new AnnotationParser(false) { @Override - protected void visitAttr(String type, String attr, String value) { + protected void visitAttr(String type, String attr, String at, String value) { if (type.equals(jvmType)) { found[0] = true; for (int i = 0; i < attrNames.length; i++) { @@ -1111,4 +1144,38 @@ } return " = null;"; } + + private static void generateAnno(ClassData cd, final Appendable out, byte[] data) throws IOException { + AnnotationParser ap = new AnnotationParser(true) { + int anno; + int cnt; + + @Override + protected void visitAnnotationStart(String type) throws IOException { + if (anno++ > 0) { + out.append(","); + } + out.append('"').append(type).append("\" : {\n"); + cnt = 0; + } + + @Override + protected void visitAnnotationEnd(String type) throws IOException { + out.append("\n}\n"); + } + + @Override + protected void visitAttr(String type, String attr, String attrType, String value) + throws IOException { + if (attr == null) { + return; + } + if (cnt++ > 0) { + out.append(",\n"); + } + out.append(attr).append("__").append(attrType).append(" : ").append(value); + } + }; + ap.parse(data, cd); + } } diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Tue Dec 04 09:16:53 2012 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/GenJS.java Wed Dec 05 10:52:50 2012 +0100 @@ -91,19 +91,20 @@ ); } } - for (String resource : js.scripts.toArray()) { - while (resource.startsWith("/")) { - resource = resource.substring(1); - } - InputStream emul = l.getResourceAsStream(resource); - if (emul == null) { - throw new IOException("Can't find " + resource); - } - readResource(emul, out); - } - js.scripts = new StringArray(); } + for (String resource : js.scripts.toArray()) { + while (resource.startsWith("/")) { + resource = resource.substring(1); + } + InputStream emul = l.getResourceAsStream(resource); + if (emul == null) { + throw new IOException("Can't find " + resource); + } + readResource(emul, out); + } + js.scripts = new StringArray(); + StringArray toInit = StringArray.asList(js.references.toArray()); toInit.reverse(); diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,132 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import javax.script.Invocable; +import org.testng.annotations.Test; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; + +/** + * + * @author Jaroslav Tulach + */ +public class ClassTest { + + @Test public void superClassEqualsGetSuperclass() { + assertTrue(Classes.equalsClassesOfExceptions(), "Classes are equal"); + } + + @Test public void jsSuperClassEqualsGetSuperclass() throws Exception { + assertExec("Classes are equal", Classes.class, "equalsClassesOfExceptions__Z", Double.valueOf(1.0)); + } + + @Test public void classesAreDifferent() { + assertTrue(Classes.differenceInClasses(), "Classes are not equal"); + } + + @Test public void jsClassesAreDifferent() throws Exception { + assertExec("Classes are not equal", Classes.class, "differenceInClasses__Z", Double.valueOf(1.0)); + } + + @Test public void javaInstanceName() throws Exception { + assertEquals(Classes.classForInstance(), "java.io.IOException"); + } + @Test public void jsInstanceName() throws Exception { + assertExec("I/O name", Classes.class, "classForInstance__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaName() throws Exception { + assertEquals(Classes.name(), "java.io.IOException"); + } + @Test public void jsName() throws Exception { + assertExec("I/O name", Classes.class, "name__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaSimpleName() throws Exception { + assertEquals(Classes.simpleName(), "IOException"); + } + @Test public void jsGetsSimpleName() throws Exception { + assertExec("I/O simple name", Classes.class, "simpleName__Ljava_lang_String_2", "IOException"); + } + @Test public void javaCanonicalName() { + assertEquals(Classes.canonicalName(), "java.io.IOException"); + } + @Test public void jsCanonicalName() throws Exception { + assertExec("I/O simple name", Classes.class, "canonicalName__Ljava_lang_String_2", "java.io.IOException"); + } + @Test public void javaNewInstance() throws Exception { + assertTrue(Classes.newInstance()); + } + @Test public void jsNewInstance() throws Exception { + assertExec("Check new instance", Classes.class, "newInstance__Z", Double.valueOf(1)); + } + @Test public void jsAnnotation() throws Exception { + assertExec("Check class annotation", Classes.class, "getMarker__I", Double.valueOf(10)); + } + @Test public void jsStringAnnotation() throws Exception { + assertExec("Check class annotation", Classes.class, "getNamer__Ljava_lang_String_2Z", "my text", true); + } + @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, "name"), "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_2ZLjava_lang_String_2", + "java.io.IOException", true, "name" + ); + } + @Test public void javaFindMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(false, "name"), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsFindMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2", + "java.io.IOException", false, "name" + ); + } + @Test public void javaAnnotatedMethod() throws Exception { + assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection"); + } + @Test public void jsAnnotatedMethod() throws Exception { + assertExec("Calls the name() method via reflection", Classes.class, + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2", + "java.io.IOException", false, null + ); + } + + private static CharSequence codeSeq; + private static Invocable code; + + @BeforeClass + public void compileTheCode() throws Exception { + if (codeSeq == null) { + StringBuilder sb = new StringBuilder(); + code = StaticMethodTest.compileClass(sb, "org/apidesign/vm4brwsr/Classes"); + codeSeq = sb; + } + } + + private void assertExec( + String msg, Class clazz, String method, Object expRes, Object... args + ) throws Exception { + StaticMethodTest.assertExec(code, codeSeq, msg, clazz, method, expRes, args); + } + +} diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/test/java/org/apidesign/vm4brwsr/Classes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,114 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import org.apidesign.bck2brwsr.core.JavaScriptBody; + +/** + * + * @author Jaroslav Tulach + */ +@ClassesMarker(number = 10) +@ClassesNamer(name = "my text") +public class Classes { + public static boolean equalsClassesOfExceptions() { + return MalformedURLException.class.getSuperclass() == IOException.class; + } + public static boolean differenceInClasses() { + Class c1 = MalformedURLException.class; + Class c2 = IOException.class; + return c1 != c2; + } + + public static String classForInstance() { + return new IOException().getClass().getName().toString(); + } + + @ClassesMarker(number = 1) + public static String name() { + return IOException.class.getName().toString(); + } + public static String simpleName() { + return IOException.class.getSimpleName(); + } + public static String canonicalName() { + return IOException.class.getCanonicalName(); + } + public static boolean newInstance() throws Exception { + IOException ioe = IOException.class.newInstance(); + if (ioe instanceof IOException) { + return ioe.getClass() == IOException.class; + } + throw new IllegalStateException("Not a subtype: " + ioe); + } + public static int getMarker() { + if (!Classes.class.isAnnotationPresent(ClassesMarker.class)) { + return -2; + } + ClassesMarker cm = Classes.class.getAnnotation(ClassesMarker.class); + return cm == null ? -1 : cm.number(); + } + public static String getNamer(boolean direct) { + if (direct) { + ClassesNamer cm = Classes.class.getAnnotation(ClassesNamer.class); + return cm == null ? null : cm.name(); + } + for (Annotation a : Classes.class.getAnnotations()) { + if (a instanceof ClassesNamer) { + return ((ClassesNamer)a).name(); + } + } + return null; + } + + @JavaScriptBody(args = "msg", body = "throw msg;") + private static native void thrw(String msg); + + public static Object reflectiveMethodCall(boolean direct, String mn) throws Exception { + Method find = null; + StringBuilder sb = new StringBuilder(); + if (!direct) { + final Class v = ClassesMarker.class; + for (Method m : Classes.class.getMethods()) { + sb.append("\n").append(m.getName()); + if (mn != null) { + if (m.getName().equals(mn)) { + find = m; + break; + } + } else { + if (m.getAnnotation(v) != null) { + find = m; + break; + } + } + } + } else { + find = Classes.class.getMethod(mn); + } + if (find == null) { + thrw(sb.toString()); + throw new NullPointerException(sb.toString()); + } + return find.invoke(null); + } +} diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesMarker.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,30 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassesMarker { + int number(); +} diff -r 0bfcb6585290 -r 79697fa91bfc vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassesNamer.java Wed Dec 05 10:52:50 2012 +0100 @@ -0,0 +1,30 @@ +/** + * Back 2 Browser Bytecode Translator + * Copyright (C) 2012 Jaroslav Tulach + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. Look for COPYING file in the top folder. + * If not, see http://opensource.org/licenses/GPL-2.0. + */ +package org.apidesign.vm4brwsr; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * + * @author Jaroslav Tulach + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface ClassesNamer { + String name(); +}