# HG changeset patch # User Jaroslav Tulach # Date 1352675254 -3600 # Node ID 2cda429aeb49d32124f6fbbb043af12323d2b504 # Parent 40f95fe90cdcc1bc3079c6fe6477f92456432394 Some support for annotations diff -r 40f95fe90cdc -r 2cda429aeb49 javap/pom.xml --- a/javap/pom.xml Sun Nov 11 13:23:52 2012 +0100 +++ b/javap/pom.xml Mon Nov 12 00:07:34 2012 +0100 @@ -23,7 +23,7 @@ 2.5.1 - non-existing + 1.6 1.6 diff -r 40f95fe90cdc -r 2cda429aeb49 javap/src/main/java/sun/tools/javap/AnnotationParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javap/src/main/java/sun/tools/javap/AnnotationParser.java Mon Nov 12 00:07:34 2012 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2002, 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 sun.tools.javap; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; + +/** An abstract parser for annotation definitions. Analyses the bytes and + * performs some callbacks to the overriden parser methods. + * + * @author Jaroslav Tulach + */ +public class AnnotationParser { + protected AnnotationParser() { + } + + protected void visitAttr(String type, String attr, String value) { + } + + /** Initialize the parsing with constant pool from cd. + * + * @param attr the attribute defining annotations + * @param cd constant pool + * @throws IOException in case I/O fails + */ + public final void parse(byte[] attr, ClassData cd) throws IOException { + ByteArrayInputStream is = new ByteArrayInputStream(attr); + DataInputStream dis = new DataInputStream(is); + try { + read(dis, cd); + } finally { + is.close(); + } + } + + private void read(DataInputStream dis, ClassData cd) throws IOException { + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + readAnno(dis, cd); + } + } + + private void readAnno(DataInputStream dis, ClassData cd) throws IOException { + int type = dis.readUnsignedShort(); + String typeName = cd.StringValue(type); + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + readCmp(dis, cd, typeName); + } + } + + private void readCmp(DataInputStream dis, ClassData cd, String typeName) + throws IOException { + String name = cd.StringValue(dis.readUnsignedShort()); + char type = (char)dis.readByte(); + if (type == '@') { + readAnno(dis, cd); + } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N + int primitive = dis.readUnsignedShort(); + visitAttr(typeName, name, cd.StringValue(primitive)); + } else if (type == 'c') { + int cls = dis.readUnsignedShort(); + } else if (type == '[') { + int cnt = dis.readUnsignedShort(); + for (int i = 0; i < cnt; i++) { + readCmp(dis, cd, typeName); + } + } else if (type == 'e') { + int enumT = dis.readUnsignedShort(); + int enumN = dis.readUnsignedShort(); + } else { + throw new IOException("Unknown type " + type); + } + } +} diff -r 40f95fe90cdc -r 2cda429aeb49 javap/src/main/java/sun/tools/javap/ClassData.java --- a/javap/src/main/java/sun/tools/javap/ClassData.java Sun Nov 11 13:23:52 2012 +0100 +++ b/javap/src/main/java/sun/tools/javap/ClassData.java Mon Nov 12 00:07:34 2012 +0100 @@ -373,9 +373,16 @@ /** * Returns list of attributes. */ - public AttrData[] getAttributes(){ + final AttrData[] getAttributes(){ return attrs; } + + public byte[] findAnnotationData(boolean classRetention) { + String n = classRetention ? + "RuntimeInvisibleAnnotations" : // NOI18N + "RuntimeVisibleAnnotations"; // NOI18N + return findAttr(n, attrs); + } /** * Returns true if superbit is set. @@ -695,4 +702,13 @@ arr[0] = getClassName(c2.cpx1); return getNameAndType(c2.cpx2, 1, arr); } + + static byte[] findAttr(String n, AttrData[] attrs) { + for (AttrData ad : attrs) { + if (n.equals(ad.getAttrName())) { + return ad.getData(); + } + } + return null; + } } diff -r 40f95fe90cdc -r 2cda429aeb49 javap/src/main/java/sun/tools/javap/MethodData.java --- a/javap/src/main/java/sun/tools/javap/MethodData.java Sun Nov 11 13:23:52 2012 +0100 +++ b/javap/src/main/java/sun/tools/javap/MethodData.java Mon Nov 12 00:07:34 2012 +0100 @@ -25,8 +25,8 @@ package sun.tools.javap; -import java.util.*; import java.io.*; +import org.apidesign.bck2brwsr.core.JavaScriptBody; import static sun.tools.javap.RuntimeConstants.*; @@ -413,4 +413,13 @@ public boolean isDeprecated(){ return isDeprecated; } + + public byte[] findAnnotationData(boolean classRetention) { + String n = classRetention ? + "RuntimeInvisibleAnnotations" : // NOI18N + "RuntimeVisibleAnnotations"; // NOI18N + AttrData[] arr = new AttrData[attrs.size()]; + attrs.copyInto(arr); + return ClassData.findAttr(n, arr); + } } diff -r 40f95fe90cdc -r 2cda429aeb49 javap/src/main/java/sun/tools/javap/Vector.java --- a/javap/src/main/java/sun/tools/javap/Vector.java Sun Nov 11 13:23:52 2012 +0100 +++ b/javap/src/main/java/sun/tools/javap/Vector.java Mon Nov 12 00:07:34 2012 +0100 @@ -31,8 +31,14 @@ return arr == null ? 0 : arr.length; } - void copyInto(Object[] accflags) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + void copyInto(Object[] newArr) { + if (arr == null) { + return; + } + int min = Math.min(newArr.length, arr.length); + for (int i = 0; i < min; i++) { + newArr[i] = arr[i]; + } } Object elementAt(int index) { @@ -40,16 +46,9 @@ } void setSize(int len) { - if (arr == null) { - arr = new Object[len]; - } else { - Object[] newArr = new Object[len]; - int min = Math.min(len, arr.length); - for (int i = 0; i < min; i++) { - newArr[i] = arr[i]; - } - arr = newArr; - } + Object[] newArr = new Object[len]; + copyInto(newArr); + arr = newArr; } void setElementAt(Object val, int index) { diff -r 40f95fe90cdc -r 2cda429aeb49 vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java --- a/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Sun Nov 11 13:23:52 2012 +0100 +++ b/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java Mon Nov 12 00:07:34 2012 +0100 @@ -24,6 +24,7 @@ import java.util.List; import org.apidesign.bck2brwsr.core.ExtraJavaScript; import org.apidesign.bck2brwsr.core.JavaScriptBody; +import sun.tools.javap.AnnotationParser; import sun.tools.javap.ClassData; import sun.tools.javap.FieldData; import sun.tools.javap.MethodData; @@ -68,19 +69,14 @@ Collection scripts ) throws IOException { ClassData jc = new ClassData(classFile); - /* - final ClassName extraAnn = ClassName.getClassName(ExtraJavaScript.class.getName().replace('.', '/')); - Annotation a = jc.getAnnotation(extraAnn); - if (a != null) { - final ElementValue annVal = a.getComponent("resource").getValue(); - String res = ((PrimitiveElementValue)annVal).getValue().getValue().toString(); - scripts.add(res); - final AnnotationComponent process = a.getComponent("processByteCode"); - if (process != null && "const=0".equals(process.getValue().toString())) { + byte[] arrData = jc.findAnnotationData(true); + String[] arr = findAnnotation(arrData, jc, ExtraJavaScript.class.getName(), "resource", "processByteCode"); + if (arr != null) { + scripts.add(arr[0]); + if ("0".equals(arr[1])) { return null; } } - */ ByteCodeToJavaScript compiler = new ByteCodeToJavaScript( jc, out, references ); @@ -989,51 +985,89 @@ } private boolean javaScriptBody(MethodData m, boolean isStatic) throws IOException { - return false; - /* - final ClassName extraAnn = ClassName.getClassName(JavaScriptBody.class.getName().replace('.', '/')); - Annotation a = m.getAnnotation(extraAnn); - if (a != null) { - final ElementValue annVal = a.getComponent("body").getValue(); - String body = ((PrimitiveElementValue) annVal).getValue().getValue().toString(); + byte[] arr = m.findAnnotationData(true); + if (arr == null) { + return false; + } + final String jvmType = "L" + JavaScriptBody.class.getName().replace('.', '/') + ";"; + class P extends AnnotationParser { + int cnt; + String[] args = new String[30]; + String body; - final ArrayElementValue arrVal = (ArrayElementValue) a.getComponent("args").getValue(); - final int len = arrVal.getValues().length; - String[] names = new String[len]; - for (int i = 0; i < len; i++) { - names[i] = ((PrimitiveElementValue) arrVal.getValues()[i]).getValue().getValue().toString(); + @Override + protected void visitAttr(String type, String attr, String value) { + if (type.equals(jvmType)) { + if ("body".equals(attr)) { + body = value; + } else if ("args".equals(attr)) { + args[cnt++] = value; + } else { + throw new IllegalArgumentException(attr); + } + } } - out.append("\nfunction ").append( - jc.getName().getInternalName().replace('/', '_')).append('_').append(findMethodName(m)); - out.append("("); - String space; - int index; - if (!isStatic) { - out.append(names[0]); - space = ","; - index = 1; - } else { - space = ""; - index = 0; - } - List args = m.getParameters(); - for (int i = 0; i < args.size(); i++) { - out.append(space); - out.append(names[index]); - final String desc = findDescriptor(args.get(i).getDescriptor()); - index++; - space = ","; - } - out.append(") {").append("\n"); - out.append(body); - out.append("\n}\n"); - return true; } - return false; - */ + P p = new P(); + p.parse(arr, jc); + if (p.body == null) { + return false; + } + int argsCnt[] = { -1 }; + out.append("\nfunction ").append(className(jc)).append('_'). + append(findMethodName(m, argsCnt)); + out.append("("); + String space; + int index; + if (!isStatic) { + out.append(p.args[0]); + space = ","; + index = 1; + } else { + space = ""; + index = 0; + } + for (int i = 0; i < argsCnt[0]; i++) { + out.append(space); + out.append(p.args[index]); + index++; + space = ","; + } + out.append(") {").append("\n"); + out.append(p.body); + out.append("\n}\n"); + return true; } private static String className(ClassData jc) { //return jc.getName().getInternalName().replace('/', '_'); return jc.getClassName().replace('/', '_'); } + + private static String[] findAnnotation( + byte[] arr, ClassData cd, final String className, + final String... attrNames + ) throws IOException { + if (arr == null) { + return null; + } + final String[] values = new String[attrNames.length]; + final boolean[] found = { false }; + final String jvmType = "L" + className.replace('.', '/') + ";"; + AnnotationParser ap = new AnnotationParser() { + @Override + protected void visitAttr(String type, String attr, String value) { + if (type.equals(jvmType)) { + found[0] = true; + for (int i = 0; i < attrNames.length; i++) { + if (attrNames[i].equals(attr)) { + values[i] = value; + } + } + } + } + + }; + ap.parse(arr, cd); + return found[0] ? values : null; + } }