Some support for annotations javap
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Mon, 12 Nov 2012 00:07:34 +0100
branchjavap
changeset 1522cda429aeb49
parent 151 40f95fe90cdc
child 153 79aeed4723b8
Some support for annotations
javap/pom.xml
javap/src/main/java/sun/tools/javap/AnnotationParser.java
javap/src/main/java/sun/tools/javap/ClassData.java
javap/src/main/java/sun/tools/javap/MethodData.java
javap/src/main/java/sun/tools/javap/Vector.java
vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java
     1.1 --- a/javap/pom.xml	Sun Nov 11 13:23:52 2012 +0100
     1.2 +++ b/javap/pom.xml	Mon Nov 12 00:07:34 2012 +0100
     1.3 @@ -23,7 +23,7 @@
     1.4                <version>2.5.1</version>
     1.5                <configuration>
     1.6                    <compilerArguments>
     1.7 -                      <bootclasspath>non-existing</bootclasspath>
     1.8 +                      <!--<bootclasspath>non-existing</bootclasspath>-->
     1.9                    </compilerArguments>
    1.10                   <source>1.6</source>
    1.11                   <target>1.6</target>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/javap/src/main/java/sun/tools/javap/AnnotationParser.java	Mon Nov 12 00:07:34 2012 +0100
     2.3 @@ -0,0 +1,98 @@
     2.4 +/*
     2.5 + * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
     2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.7 + *
     2.8 + * This code is free software; you can redistribute it and/or modify it
     2.9 + * under the terms of the GNU General Public License version 2 only, as
    2.10 + * published by the Free Software Foundation.  Oracle designates this
    2.11 + * particular file as subject to the "Classpath" exception as provided
    2.12 + * by Oracle in the LICENSE file that accompanied this code.
    2.13 + *
    2.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    2.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    2.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    2.17 + * version 2 for more details (a copy is included in the LICENSE file that
    2.18 + * accompanied this code).
    2.19 + *
    2.20 + * You should have received a copy of the GNU General Public License version
    2.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    2.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    2.23 + *
    2.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    2.25 + * or visit www.oracle.com if you need additional information or have any
    2.26 + * questions.
    2.27 + */
    2.28 +package sun.tools.javap;
    2.29 +
    2.30 +import java.io.ByteArrayInputStream;
    2.31 +import java.io.DataInputStream;
    2.32 +import java.io.IOException;
    2.33 +
    2.34 +/** An abstract parser for annotation definitions. Analyses the bytes and
    2.35 + * performs some callbacks to the overriden parser methods.
    2.36 + *
    2.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    2.38 + */
    2.39 +public class AnnotationParser {
    2.40 +    protected AnnotationParser() {
    2.41 +    }
    2.42 +
    2.43 +    protected void visitAttr(String type, String attr, String value) {
    2.44 +    }
    2.45 +    
    2.46 +    /** Initialize the parsing with constant pool from <code>cd</code>.
    2.47 +     * 
    2.48 +     * @param attr the attribute defining annotations
    2.49 +     * @param cd constant pool
    2.50 +     * @throws IOException in case I/O fails
    2.51 +     */
    2.52 +    public final void parse(byte[] attr, ClassData cd) throws IOException {
    2.53 +        ByteArrayInputStream is = new ByteArrayInputStream(attr);
    2.54 +        DataInputStream dis = new DataInputStream(is);
    2.55 +        try {
    2.56 +            read(dis, cd);
    2.57 +        } finally {
    2.58 +            is.close();
    2.59 +        }
    2.60 +    }
    2.61 +    
    2.62 +    private void read(DataInputStream dis, ClassData cd) throws IOException {
    2.63 +    	int cnt = dis.readUnsignedShort();
    2.64 +        for (int i = 0; i < cnt; i++) {
    2.65 +            readAnno(dis, cd);
    2.66 +        }
    2.67 +    }
    2.68 +
    2.69 +    private void readAnno(DataInputStream dis, ClassData cd) throws IOException {
    2.70 +        int type = dis.readUnsignedShort();
    2.71 +        String typeName = cd.StringValue(type);
    2.72 +    	int cnt = dis.readUnsignedShort();
    2.73 +    	for (int i = 0; i < cnt; i++) {
    2.74 +            readCmp(dis, cd, typeName);
    2.75 +        }
    2.76 +    }
    2.77 +
    2.78 +    private void readCmp(DataInputStream dis, ClassData cd, String typeName) 
    2.79 +    throws IOException {
    2.80 +        String name = cd.StringValue(dis.readUnsignedShort());
    2.81 +        char type = (char)dis.readByte();
    2.82 +        if (type == '@') {
    2.83 +            readAnno(dis, cd);
    2.84 +        } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
    2.85 +            int primitive = dis.readUnsignedShort();
    2.86 +            visitAttr(typeName, name, cd.StringValue(primitive));
    2.87 +        } else if (type == 'c') {
    2.88 +            int cls = dis.readUnsignedShort();
    2.89 +        } else if (type == '[') {
    2.90 +            int cnt = dis.readUnsignedShort();
    2.91 +            for (int i = 0; i < cnt; i++) {
    2.92 +                readCmp(dis, cd, typeName);
    2.93 +            }
    2.94 +        } else if (type == 'e') {
    2.95 +            int enumT = dis.readUnsignedShort();
    2.96 +            int enumN = dis.readUnsignedShort();
    2.97 +        } else {
    2.98 +            throw new IOException("Unknown type " + type);
    2.99 +        }
   2.100 +    }
   2.101 +}
     3.1 --- a/javap/src/main/java/sun/tools/javap/ClassData.java	Sun Nov 11 13:23:52 2012 +0100
     3.2 +++ b/javap/src/main/java/sun/tools/javap/ClassData.java	Mon Nov 12 00:07:34 2012 +0100
     3.3 @@ -373,9 +373,16 @@
     3.4      /**
     3.5       * Returns list of attributes.
     3.6       */
     3.7 -    public AttrData[] getAttributes(){
     3.8 +    final AttrData[] getAttributes(){
     3.9          return attrs;
    3.10      }
    3.11 +    
    3.12 +    public byte[] findAnnotationData(boolean classRetention) {
    3.13 +        String n = classRetention ?
    3.14 +            "RuntimeInvisibleAnnotations" : // NOI18N
    3.15 +            "RuntimeVisibleAnnotations"; // NOI18N
    3.16 +        return findAttr(n, attrs);
    3.17 +    }
    3.18  
    3.19      /**
    3.20       * Returns true if superbit is set.
    3.21 @@ -695,4 +702,13 @@
    3.22          arr[0] = getClassName(c2.cpx1);
    3.23          return getNameAndType(c2.cpx2, 1, arr);
    3.24      }
    3.25 +
    3.26 +    static byte[] findAttr(String n, AttrData[] attrs) {
    3.27 +        for (AttrData ad : attrs) {
    3.28 +            if (n.equals(ad.getAttrName())) {
    3.29 +                return ad.getData();
    3.30 +            }
    3.31 +        }
    3.32 +        return null;
    3.33 +    }
    3.34  }
     4.1 --- a/javap/src/main/java/sun/tools/javap/MethodData.java	Sun Nov 11 13:23:52 2012 +0100
     4.2 +++ b/javap/src/main/java/sun/tools/javap/MethodData.java	Mon Nov 12 00:07:34 2012 +0100
     4.3 @@ -25,8 +25,8 @@
     4.4  
     4.5  package sun.tools.javap;
     4.6  
     4.7 -import java.util.*;
     4.8  import java.io.*;
     4.9 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    4.10  
    4.11  import static sun.tools.javap.RuntimeConstants.*;
    4.12  
    4.13 @@ -413,4 +413,13 @@
    4.14      public boolean isDeprecated(){
    4.15          return isDeprecated;
    4.16      }
    4.17 +
    4.18 +    public byte[] findAnnotationData(boolean classRetention) {
    4.19 +        String n = classRetention ?
    4.20 +            "RuntimeInvisibleAnnotations" : // NOI18N
    4.21 +            "RuntimeVisibleAnnotations"; // NOI18N
    4.22 +        AttrData[] arr = new AttrData[attrs.size()];
    4.23 +        attrs.copyInto(arr);
    4.24 +        return ClassData.findAttr(n, arr);
    4.25 +    }
    4.26  }
     5.1 --- a/javap/src/main/java/sun/tools/javap/Vector.java	Sun Nov 11 13:23:52 2012 +0100
     5.2 +++ b/javap/src/main/java/sun/tools/javap/Vector.java	Mon Nov 12 00:07:34 2012 +0100
     5.3 @@ -31,8 +31,14 @@
     5.4          return arr == null ? 0 : arr.length;
     5.5      }
     5.6  
     5.7 -    void copyInto(Object[] accflags) {
     5.8 -        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
     5.9 +    void copyInto(Object[] newArr) {
    5.10 +        if (arr == null) {
    5.11 +            return;
    5.12 +        }
    5.13 +        int min = Math.min(newArr.length, arr.length);
    5.14 +        for (int i = 0; i < min; i++) {
    5.15 +            newArr[i] = arr[i];
    5.16 +        }
    5.17      }
    5.18  
    5.19      Object elementAt(int index) {
    5.20 @@ -40,16 +46,9 @@
    5.21      }
    5.22  
    5.23      void setSize(int len) {
    5.24 -        if (arr == null) {
    5.25 -            arr = new Object[len];
    5.26 -        } else {
    5.27 -            Object[] newArr = new Object[len];
    5.28 -            int min = Math.min(len, arr.length);
    5.29 -            for (int i = 0; i < min; i++) {
    5.30 -                newArr[i] = arr[i];
    5.31 -            }
    5.32 -            arr = newArr;
    5.33 -        }
    5.34 +        Object[] newArr = new Object[len];
    5.35 +        copyInto(newArr);
    5.36 +        arr = newArr;
    5.37      }
    5.38  
    5.39      void setElementAt(Object val, int index) {
     6.1 --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Sun Nov 11 13:23:52 2012 +0100
     6.2 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Nov 12 00:07:34 2012 +0100
     6.3 @@ -24,6 +24,7 @@
     6.4  import java.util.List;
     6.5  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
     6.6  import org.apidesign.bck2brwsr.core.JavaScriptBody;
     6.7 +import sun.tools.javap.AnnotationParser;
     6.8  import sun.tools.javap.ClassData;
     6.9  import sun.tools.javap.FieldData;
    6.10  import sun.tools.javap.MethodData;
    6.11 @@ -68,19 +69,14 @@
    6.12          Collection<? super String> scripts
    6.13      ) throws IOException {
    6.14          ClassData jc = new ClassData(classFile);
    6.15 -        /*
    6.16 -        final ClassName extraAnn = ClassName.getClassName(ExtraJavaScript.class.getName().replace('.', '/'));
    6.17 -        Annotation a = jc.getAnnotation(extraAnn);
    6.18 -        if (a != null) {
    6.19 -            final ElementValue annVal = a.getComponent("resource").getValue();
    6.20 -            String res = ((PrimitiveElementValue)annVal).getValue().getValue().toString();
    6.21 -            scripts.add(res);
    6.22 -            final AnnotationComponent process = a.getComponent("processByteCode");
    6.23 -            if (process != null && "const=0".equals(process.getValue().toString())) {
    6.24 +        byte[] arrData = jc.findAnnotationData(true);
    6.25 +        String[] arr = findAnnotation(arrData, jc, ExtraJavaScript.class.getName(), "resource", "processByteCode");
    6.26 +        if (arr != null) {
    6.27 +            scripts.add(arr[0]);
    6.28 +            if ("0".equals(arr[1])) {
    6.29                  return null;
    6.30              }
    6.31          }
    6.32 -        */
    6.33          ByteCodeToJavaScript compiler = new ByteCodeToJavaScript(
    6.34              jc, out, references
    6.35          );
    6.36 @@ -989,51 +985,89 @@
    6.37      }
    6.38  
    6.39      private boolean javaScriptBody(MethodData m, boolean isStatic) throws IOException {
    6.40 -        return false;
    6.41 -        /*
    6.42 -        final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/'));
    6.43 -        Annotation a = m.getAnnotation(extraAnn);
    6.44 -        if (a != null) {
    6.45 -            final ElementValue annVal = a.getComponent("body").getValue();
    6.46 -            String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString();
    6.47 +        byte[] arr = m.findAnnotationData(true);
    6.48 +        if (arr == null) {
    6.49 +            return false;
    6.50 +        }
    6.51 +        final String jvmType = "L" + JavaScriptBody.class.getName().replace('.', '/') + ";";
    6.52 +        class P extends AnnotationParser {
    6.53 +            int cnt;
    6.54 +            String[] args = new String[30];
    6.55 +            String body;
    6.56              
    6.57 -            final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue();
    6.58 -            final int len = arrVal.getValues().length;
    6.59 -            String[] names = new String[len];
    6.60 -            for (int i = 0; i < len; i++) {
    6.61 -                names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString();
    6.62 +            @Override
    6.63 +            protected void visitAttr(String type, String attr, String value) {
    6.64 +                if (type.equals(jvmType)) {
    6.65 +                    if ("body".equals(attr)) {
    6.66 +                        body = value;
    6.67 +                    } else if ("args".equals(attr)) {
    6.68 +                        args[cnt++] = value;
    6.69 +                    } else {
    6.70 +                        throw new IllegalArgumentException(attr);
    6.71 +                    }
    6.72 +                }
    6.73              }
    6.74 -            out.append("\nfunction ").append(
    6.75 -                jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m));
    6.76 -            out.append("(");
    6.77 -            String space;
    6.78 -            int index;
    6.79 -            if (!isStatic) {                
    6.80 -                out.append(names[0]);
    6.81 -                space = ",";
    6.82 -                index = 1;
    6.83 -            } else {
    6.84 -                space = "";
    6.85 -                index = 0;
    6.86 -            }
    6.87 -            List<Parameter> args = m.getParameters();
    6.88 -            for (int i = 0; i < args.size(); i++) {
    6.89 -                out.append(space);
    6.90 -                out.append(names[index]);
    6.91 -                final String desc = findDescriptor(args.get(i).getDescriptor());
    6.92 -                index++;
    6.93 -                space = ",";
    6.94 -            }
    6.95 -            out.append(") {").append("\n");
    6.96 -            out.append(body);
    6.97 -            out.append("\n}\n");
    6.98 -            return true;
    6.99          }
   6.100 -        return false;
   6.101 -        */
   6.102 +        P p = new P();
   6.103 +        p.parse(arr, jc);
   6.104 +        if (p.body == null) {
   6.105 +            return false;
   6.106 +        }
   6.107 +        int argsCnt[] = { -1 };
   6.108 +        out.append("\nfunction ").append(className(jc)).append('_').
   6.109 +            append(findMethodName(m, argsCnt));
   6.110 +        out.append("(");
   6.111 +        String space;
   6.112 +        int index;
   6.113 +        if (!isStatic) {                
   6.114 +            out.append(p.args[0]);
   6.115 +            space = ",";
   6.116 +            index = 1;
   6.117 +        } else {
   6.118 +            space = "";
   6.119 +            index = 0;
   6.120 +        }
   6.121 +        for (int i = 0; i < argsCnt[0]; i++) {
   6.122 +            out.append(space);
   6.123 +            out.append(p.args[index]);
   6.124 +            index++;
   6.125 +            space = ",";
   6.126 +        }
   6.127 +        out.append(") {").append("\n");
   6.128 +        out.append(p.body);
   6.129 +        out.append("\n}\n");
   6.130 +        return true;
   6.131      }
   6.132      private static String className(ClassData jc) {
   6.133          //return jc.getName().getInternalName().replace('/', '_');
   6.134          return jc.getClassName().replace('/', '_');
   6.135      }
   6.136 +    
   6.137 +    private static String[] findAnnotation(
   6.138 +        byte[] arr, ClassData cd, final String className, 
   6.139 +        final String... attrNames
   6.140 +    ) throws IOException {
   6.141 +        if (arr == null) {
   6.142 +            return null;
   6.143 +        }
   6.144 +        final String[] values = new String[attrNames.length];
   6.145 +        final boolean[] found = { false };
   6.146 +        final String jvmType = "L" + className.replace('.', '/') + ";";
   6.147 +        AnnotationParser ap = new AnnotationParser() {
   6.148 +            @Override
   6.149 +            protected void visitAttr(String type, String attr, String value) {
   6.150 +                if (type.equals(jvmType)) {
   6.151 +                    found[0] = true;
   6.152 +                    for (int i = 0; i < attrNames.length; i++) {
   6.153 +                        if (attrNames[i].equals(attr)) {
   6.154 +                            values[i] = value;
   6.155 +                        }
   6.156 +                    }
   6.157 +                }
   6.158 +            }
   6.159 +            
   6.160 +        };
   6.161 +        ap.parse(arr, cd);
   6.162 +        return found[0] ? values : null;
   6.163 +    }
   6.164  }