1.1 --- a/emul/src/main/java/java/lang/AnnotationImpl.java Wed Dec 05 09:31:36 2012 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,68 +0,0 @@
1.4 -/*
1.5 - * To change this template, choose Tools | Templates
1.6 - * and open the template in the editor.
1.7 - */
1.8 -package java.lang;
1.9 -
1.10 -import java.lang.annotation.Annotation;
1.11 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.12 -
1.13 -/**
1.14 - *
1.15 - * @author Jaroslav Tulach <jtulach@netbeans.org>
1.16 - */
1.17 -final class AnnotationImpl implements Annotation {
1.18 - public Class<? extends Annotation> annotationType() {
1.19 - return getClass();
1.20 - }
1.21 -
1.22 - @JavaScriptBody(args = { "a", "n", "values" }, body = ""
1.23 - + "function f(v, p) {\n"
1.24 - + " var val = v;\n"
1.25 - + " var prop = p;\n"
1.26 - + " return function() {\n"
1.27 - + " return val[prop];\n"
1.28 - + " };\n"
1.29 - + "}\n"
1.30 - + "var props = Object.getOwnPropertyNames(values);\n"
1.31 - + "for (var i = 0; i < props.length; i++) {\n"
1.32 - + " var p = props[i];\n"
1.33 - + " a[p] = new f(values, p);\n"
1.34 - + "}\n"
1.35 - + "a['$instOf_' + n] = true;\n"
1.36 - + "return a;"
1.37 - )
1.38 - private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
1.39 - return null;
1.40 - }
1.41 - static <T extends Annotation> T create(Class<T> annoClass, Object values) {
1.42 - return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
1.43 - }
1.44 -
1.45 - static Annotation[] create(Object anno) {
1.46 - String[] names = findNames(anno);
1.47 - Annotation[] ret = new Annotation[names.length];
1.48 - for (int i = 0; i < names.length; i++) {
1.49 - String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
1.50 - ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
1.51 - }
1.52 - return ret;
1.53 - }
1.54 - @JavaScriptBody(args = "anno", body =
1.55 - "var arr = new Array();"
1.56 - + "var props = Object.getOwnPropertyNames(anno);\n"
1.57 - + "for (var i = 0; i < props.length; i++) {\n"
1.58 - + " var p = props[i];\n"
1.59 - + " arr.push(p);"
1.60 - + "}"
1.61 - + "return arr;"
1.62 - )
1.63 - private static String[] findNames(Object anno) {
1.64 - throw new UnsupportedOperationException();
1.65 - }
1.66 -
1.67 - @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
1.68 - private static Object findData(Object anno, String p) {
1.69 - throw new UnsupportedOperationException();
1.70 - }
1.71 -}
2.1 --- a/emul/src/main/java/java/lang/Class.java Wed Dec 05 09:31:36 2012 +0100
2.2 +++ b/emul/src/main/java/java/lang/Class.java Wed Dec 05 10:03:58 2012 +0100
2.3 @@ -25,6 +25,7 @@
2.4
2.5 package java.lang;
2.6
2.7 +import org.apidesign.bck2brwsr.emul.AnnotationImpl;
2.8 import java.io.InputStream;
2.9 import java.lang.annotation.Annotation;
2.10 import java.lang.reflect.Field;
2.11 @@ -1025,7 +1026,7 @@
2.12 body =
2.13 "if (self.anno) {"
2.14 + " return self.anno['L' + ac.jvmName + ';'];"
2.15 - + "}"
2.16 + + "} else return null;"
2.17 )
2.18 private Object getAnnotationData(Class<?> annotationClass) {
2.19 throw new UnsupportedOperationException();
3.1 --- a/emul/src/main/java/java/lang/reflect/Method.java Wed Dec 05 09:31:36 2012 +0100
3.2 +++ b/emul/src/main/java/java/lang/reflect/Method.java Wed Dec 05 10:03:58 2012 +0100
3.3 @@ -27,6 +27,7 @@
3.4
3.5 import java.lang.annotation.Annotation;
3.6 import org.apidesign.bck2brwsr.core.JavaScriptBody;
3.7 +import org.apidesign.bck2brwsr.emul.AnnotationImpl;
3.8
3.9 /**
3.10 * A {@code Method} provides information about, and access to, a single method
3.11 @@ -535,15 +536,23 @@
3.12 return Modifier.isSynthetic(getModifiers());
3.13 }
3.14
3.15 + @JavaScriptBody(args = { "self", "ac" },
3.16 + body =
3.17 + "if (self.fld_data.anno) {"
3.18 + + " return self.fld_data.anno['L' + ac.jvmName + ';'];"
3.19 + + "} else return null;"
3.20 + )
3.21 + private Object getAnnotationData(Class<?> annotationClass) {
3.22 + throw new UnsupportedOperationException();
3.23 + }
3.24 +
3.25 /**
3.26 * @throws NullPointerException {@inheritDoc}
3.27 * @since 1.5
3.28 */
3.29 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
3.30 - if (annotationClass == null)
3.31 - throw new NullPointerException();
3.32 -
3.33 - throw new UnsupportedOperationException();
3.34 + Object data = getAnnotationData(annotationClass);
3.35 + return data == null ? null : AnnotationImpl.create(annotationClass, data);
3.36 }
3.37
3.38 /**
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/emul/src/main/java/org/apidesign/bck2brwsr/emul/AnnotationImpl.java Wed Dec 05 10:03:58 2012 +0100
4.3 @@ -0,0 +1,68 @@
4.4 +/*
4.5 + * To change this template, choose Tools | Templates
4.6 + * and open the template in the editor.
4.7 + */
4.8 +package org.apidesign.bck2brwsr.emul;
4.9 +
4.10 +import java.lang.annotation.Annotation;
4.11 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
4.12 +
4.13 +/**
4.14 + *
4.15 + * @author Jaroslav Tulach <jtulach@netbeans.org>
4.16 + */
4.17 +public final class AnnotationImpl implements Annotation {
4.18 + public Class<? extends Annotation> annotationType() {
4.19 + return getClass();
4.20 + }
4.21 +
4.22 + @JavaScriptBody(args = { "a", "n", "values" }, body = ""
4.23 + + "function f(v, p) {\n"
4.24 + + " var val = v;\n"
4.25 + + " var prop = p;\n"
4.26 + + " return function() {\n"
4.27 + + " return val[prop];\n"
4.28 + + " };\n"
4.29 + + "}\n"
4.30 + + "var props = Object.getOwnPropertyNames(values);\n"
4.31 + + "for (var i = 0; i < props.length; i++) {\n"
4.32 + + " var p = props[i];\n"
4.33 + + " a[p] = new f(values, p);\n"
4.34 + + "}\n"
4.35 + + "a['$instOf_' + n] = true;\n"
4.36 + + "return a;"
4.37 + )
4.38 + private static <T extends Annotation> T create(AnnotationImpl a, String n, Object values) {
4.39 + return null;
4.40 + }
4.41 + public static <T extends Annotation> T create(Class<T> annoClass, Object values) {
4.42 + return create(new AnnotationImpl(), annoClass.getName().replace('.', '_'), values);
4.43 + }
4.44 +
4.45 + public static Annotation[] create(Object anno) {
4.46 + String[] names = findNames(anno);
4.47 + Annotation[] ret = new Annotation[names.length];
4.48 + for (int i = 0; i < names.length; i++) {
4.49 + String n = names[i].substring(1, names[i].length() - 1).replace('/', '_');
4.50 + ret[i] = create(new AnnotationImpl(), n, findData(anno, names[i]));
4.51 + }
4.52 + return ret;
4.53 + }
4.54 + @JavaScriptBody(args = "anno", body =
4.55 + "var arr = new Array();"
4.56 + + "var props = Object.getOwnPropertyNames(anno);\n"
4.57 + + "for (var i = 0; i < props.length; i++) {\n"
4.58 + + " var p = props[i];\n"
4.59 + + " arr.push(p);"
4.60 + + "}"
4.61 + + "return arr;"
4.62 + )
4.63 + private static String[] findNames(Object anno) {
4.64 + throw new UnsupportedOperationException();
4.65 + }
4.66 +
4.67 + @JavaScriptBody(args={ "anno", "p"}, body="return anno[p];")
4.68 + private static Object findData(Object anno, String p) {
4.69 + throw new UnsupportedOperationException();
4.70 + }
4.71 +}
5.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Dec 05 09:31:36 2012 +0100
5.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Wed Dec 05 10:03:58 2012 +0100
5.3 @@ -121,10 +121,17 @@
5.4 }
5.5 continue;
5.6 }
5.7 + String mn;
5.8 if (m.isStatic()) {
5.9 - generateStaticMethod("\n c.", m, toInitilize);
5.10 + mn = generateStaticMethod("\n c.", m, toInitilize);
5.11 } else {
5.12 - generateInstanceMethod("\n c.", m);
5.13 + mn = generateInstanceMethod("\n c.", m);
5.14 + }
5.15 + byte[] runAnno = m.findAnnotationData(false);
5.16 + if (runAnno != null) {
5.17 + out.append("\n c.").append(mn).append(".anno = {");
5.18 + generateAnno(jc, out, runAnno);
5.19 + out.append("\n };");
5.20 }
5.21 }
5.22 out.append("\n c.constructor = CLS;");
5.23 @@ -175,9 +182,10 @@
5.24 }
5.25 return sb.toString();
5.26 }
5.27 - private void generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
5.28 - if (javaScriptBody(prefix, m, true)) {
5.29 - return;
5.30 + private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
5.31 + String jsb = javaScriptBody(prefix, m, true);
5.32 + if (jsb != null) {
5.33 + return jsb;
5.34 }
5.35 StringBuilder argsCnt = new StringBuilder();
5.36 final String mn = findMethodName(m, argsCnt);
5.37 @@ -212,11 +220,13 @@
5.38 out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n");
5.39 }
5.40 out.append("};");
5.41 + return mn;
5.42 }
5.43
5.44 - private void generateInstanceMethod(String prefix, MethodData m) throws IOException {
5.45 - if (javaScriptBody(prefix, m, false)) {
5.46 - return;
5.47 + private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
5.48 + String jsb = javaScriptBody(prefix, m, false);
5.49 + if (jsb != null) {
5.50 + return jsb;
5.51 }
5.52 StringBuilder argsCnt = new StringBuilder();
5.53 final String mn = findMethodName(m, argsCnt);
5.54 @@ -246,6 +256,7 @@
5.55 out.append(" throw 'no code found for ").append(m.getInternalSig()).append("';\n");
5.56 }
5.57 out.append("};");
5.58 + return mn;
5.59 }
5.60
5.61 private void produceCode(byte[] byteCodes) throws IOException {
5.62 @@ -1024,10 +1035,10 @@
5.63 return s;
5.64 }
5.65
5.66 - private boolean javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
5.67 + private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
5.68 byte[] arr = m.findAnnotationData(true);
5.69 if (arr == null) {
5.70 - return false;
5.71 + return null;
5.72 }
5.73 final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
5.74 class P extends AnnotationParser {
5.75 @@ -1055,10 +1066,11 @@
5.76 P p = new P();
5.77 p.parse(arr, jc);
5.78 if (p.body == null) {
5.79 - return false;
5.80 + return null;
5.81 }
5.82 StringBuilder cnt = new StringBuilder();
5.83 - out.append(prefix).append(findMethodName(m, cnt));
5.84 + final String mn = findMethodName(m, cnt);
5.85 + out.append(prefix).append(mn);
5.86 out.append(" = function(");
5.87 String space;
5.88 int index;
5.89 @@ -1079,7 +1091,7 @@
5.90 out.append(") {").append("\n");
5.91 out.append(p.body);
5.92 out.append("\n}\n");
5.93 - return true;
5.94 + return mn;
5.95 }
5.96 private static String className(ClassData jc) {
5.97 //return jc.getName().getInternalName().replace('/', '_');
5.98 @@ -1155,6 +1167,9 @@
5.99 @Override
5.100 protected void visitAttr(String type, String attr, String attrType, String value)
5.101 throws IOException {
5.102 + if (attr == null) {
5.103 + return;
5.104 + }
5.105 if (cnt++ > 0) {
5.106 out.append(",\n");
5.107 }
6.1 --- a/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Dec 05 09:31:36 2012 +0100
6.2 +++ b/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java Wed Dec 05 10:03:58 2012 +0100
6.3 @@ -101,6 +101,15 @@
6.4 "java.io.IOException", false, "name"
6.5 );
6.6 }
6.7 + @Test public void javaAnnotatedMethod() throws Exception {
6.8 + assertEquals(Classes.reflectiveMethodCall(false, null), "java.io.IOException", "Calls the name() method via reflection");
6.9 + }
6.10 + @Test public void jsAnnotatedMethod() throws Exception {
6.11 + assertExec("Calls the name() method via reflection", Classes.class,
6.12 + "reflectiveMethodCall__Ljava_lang_Object_2ZLjava_lang_String_2",
6.13 + "java.io.IOException", false, null
6.14 + );
6.15 + }
6.16
6.17 private static CharSequence codeSeq;
6.18 private static Invocable code;