| /* |
| * Copyright (c) 2012, 2014, 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. |
| * |
| * 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. |
| */ |
| |
| import java.lang.annotation.*; |
| import java.io.*; |
| import java.net.URL; |
| import java.util.List; |
| |
| import com.sun.tools.classfile.*; |
| |
| public class ClassfileTestHelper { |
| int expected_tinvisibles = 0; |
| int expected_tvisibles = 0; |
| int expected_invisibles = 0; |
| int expected_visibles = 0; |
| |
| //Makes debugging much easier. Set to 'false' for less output. |
| public Boolean verbose = true; |
| void println(String msg) { if (verbose) System.out.println(msg); } |
| void print(String msg) { if (verbose) System.out.print(msg); } |
| |
| File writeTestFile(String fname, String source) throws IOException { |
| File f = new File(fname); |
| PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); |
| out.println(source); |
| out.close(); |
| return f; |
| } |
| |
| File compile(File f) { |
| int rc = com.sun.tools.javac.Main.compile(new String[] { |
| "-g", f.getPath() }); |
| if (rc != 0) |
| throw new Error("compilation failed. rc=" + rc); |
| String path = f.getPath(); |
| return new File(path.substring(0, path.length() - 5) + ".class"); |
| } |
| |
| ClassFile getClassFile(String name) throws IOException, ConstantPoolException { |
| URL url = getClass().getResource(name); |
| InputStream in = url.openStream(); |
| try { |
| return ClassFile.read(in); |
| } finally { |
| in.close(); |
| } |
| } |
| |
| ClassFile getClassFile(URL url) throws IOException, ConstantPoolException { |
| InputStream in = url.openStream(); |
| try { |
| return ClassFile.read(in); |
| } finally { |
| in.close(); |
| } |
| } |
| |
| /************ Helper annotations counting methods ******************/ |
| void test(ClassFile cf) { |
| test("CLASS",cf, null, null, Attribute.RuntimeVisibleTypeAnnotations, true); |
| test("CLASS",cf, null, null, Attribute.RuntimeInvisibleTypeAnnotations, false); |
| //RuntimeAnnotations since one annotation can result in two attributes. |
| test("CLASS",cf, null, null, Attribute.RuntimeVisibleAnnotations, true); |
| test("CLASS",cf, null, null, Attribute.RuntimeInvisibleAnnotations, false); |
| } |
| |
| void test(ClassFile cf, Field f, Boolean local) { |
| if (!local) { |
| test("FIELD",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true); |
| test("FIELD",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false); |
| test("FIELD",cf, f, null, Attribute.RuntimeVisibleAnnotations, true); |
| test("FIELD",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false); |
| } else { |
| test("CODE",cf, f, null, Attribute.RuntimeVisibleTypeAnnotations, true); |
| test("CODE",cf, f, null, Attribute.RuntimeInvisibleTypeAnnotations, false); |
| test("CODE",cf, f, null, Attribute.RuntimeVisibleAnnotations, true); |
| test("CODE",cf, f, null, Attribute.RuntimeInvisibleAnnotations, false); |
| } |
| } |
| |
| void test(ClassFile cf, Field f) { |
| test(cf, f, false); |
| } |
| |
| // 'local' determines whether to look for annotations in code attribute or not. |
| void test(ClassFile cf, Method m, Boolean local) { |
| if (!local) { |
| test("METHOD",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true); |
| test("METHOD",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false); |
| test("METHOD",cf, null, m, Attribute.RuntimeVisibleAnnotations, true); |
| test("METHOD",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false); |
| } else { |
| test("MCODE",cf, null, m, Attribute.RuntimeVisibleTypeAnnotations, true); |
| test("MCODE",cf, null, m, Attribute.RuntimeInvisibleTypeAnnotations, false); |
| test("MCODE",cf, null, m, Attribute.RuntimeVisibleAnnotations, true); |
| test("MCODE",cf, null, m, Attribute.RuntimeInvisibleAnnotations, false); |
| } |
| } |
| |
| // default to not looking in code attribute |
| void test(ClassFile cf, Method m ) { |
| test(cf, m, false); |
| } |
| |
| // Test the result of Attributes.getIndex according to expectations |
| // encoded in the class/field/method name; increment annotations counts. |
| void test(String ttype, ClassFile cf, Field f, Method m, String annName, boolean visible) { |
| String testtype = ttype; |
| String name = null; |
| int index = -1; |
| Attribute attr = null; |
| Code_attribute cAttr = null; |
| boolean isTAattr = annName.contains("TypeAnnotations"); |
| try { |
| switch(testtype) { |
| case "FIELD": |
| name = f.getName(cf.constant_pool); |
| index = f.attributes.getIndex(cf.constant_pool, annName); |
| if(index!= -1) |
| attr = f.attributes.get(index); |
| break; |
| case "CODE": |
| name = f.getName(cf.constant_pool); |
| //fetch index of and code attribute and annotations from code attribute. |
| index = cf.attributes.getIndex(cf.constant_pool, Attribute.Code); |
| if(index!= -1) { |
| attr = cf.attributes.get(index); |
| assert attr instanceof Code_attribute; |
| cAttr = (Code_attribute)attr; |
| index = cAttr.attributes.getIndex(cf.constant_pool, annName); |
| if(index!= -1) |
| attr = cAttr.attributes.get(index); |
| } |
| break; |
| case "METHOD": |
| name = m.getName(cf.constant_pool); |
| index = m.attributes.getIndex(cf.constant_pool, annName); |
| if(index!= -1) |
| attr = m.attributes.get(index); |
| break; |
| case "MCODE": |
| name = m.getName(cf.constant_pool); |
| //fetch index of and code attribute and annotations from code attribute. |
| index = m.attributes.getIndex(cf.constant_pool, Attribute.Code); |
| if(index!= -1) { |
| attr = m.attributes.get(index); |
| assert attr instanceof Code_attribute; |
| cAttr = (Code_attribute)attr; |
| index = cAttr.attributes.getIndex(cf.constant_pool, annName); |
| if(index!= -1) |
| attr = cAttr.attributes.get(index); |
| } |
| break; |
| default: |
| name = cf.getName(); |
| index = cf.attributes.getIndex(cf.constant_pool, annName); |
| if(index!= -1) attr = cf.attributes.get(index); |
| } |
| } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } |
| |
| if (index != -1) { |
| if(isTAattr) { //count RuntimeTypeAnnotations |
| RuntimeTypeAnnotations_attribute tAttr = |
| (RuntimeTypeAnnotations_attribute)attr; |
| println(testtype + ": " + name + ", " + annName + ": " + |
| tAttr.annotations.length ); |
| if (tAttr.annotations.length > 0) { |
| for (int i = 0; i < tAttr.annotations.length; i++) { |
| println(" types:" + tAttr.annotations[i].position.type); |
| } |
| } else { |
| println(""); |
| } |
| allt += tAttr.annotations.length; |
| if (visible) |
| tvisibles += tAttr.annotations.length; |
| else |
| tinvisibles += tAttr.annotations.length; |
| } else { |
| RuntimeAnnotations_attribute tAttr = |
| (RuntimeAnnotations_attribute)attr; |
| println(testtype + ": " + name + ", " + annName + ": " + |
| tAttr.annotations.length ); |
| all += tAttr.annotations.length; |
| if (visible) |
| visibles += tAttr.annotations.length; |
| else |
| invisibles += tAttr.annotations.length; |
| } |
| } |
| } |
| |
| void countAnnotations() { |
| errors=0; |
| int expected_allt = expected_tvisibles + expected_tinvisibles; |
| int expected_all = expected_visibles + expected_invisibles; |
| |
| if (expected_allt != allt) { |
| errors++; |
| System.err.println("Failure: expected " + expected_allt + |
| " type annotations but found " + allt); |
| } |
| if (expected_all != all) { |
| errors++; |
| System.err.println("Failure: expected " + expected_all + |
| " annotations but found " + all); |
| } |
| if (expected_tvisibles != tvisibles) { |
| errors++; |
| System.err.println("Failure: expected " + expected_tvisibles + |
| " typevisible annotations but found " + tvisibles); |
| } |
| |
| if (expected_tinvisibles != tinvisibles) { |
| errors++; |
| System.err.println("Failure: expected " + expected_tinvisibles + |
| " typeinvisible annotations but found " + tinvisibles); |
| } |
| allt=0; |
| tvisibles=0; |
| tinvisibles=0; |
| all=0; |
| visibles=0; |
| invisibles=0; |
| } |
| |
| int errors; |
| int allt; |
| int tvisibles; |
| int tinvisibles; |
| int all; |
| int visibles; |
| int invisibles; |
| } |