1 /* 2 * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.io.*; 25 import com.sun.tools.classfile.*; 26 27 /* 28 * @test PresenceInner 29 * @bug 6843077 30 * @summary test that annotations in inner types count only once 31 */ 32 33 public class PresenceInner { 34 public static void main(String[] args) throws Exception { 35 new PresenceInner().run(); 36 } 37 38 public void run() throws Exception { 39 File javaFile = writeTestFile(); 40 File classFile = compileTestFile(javaFile); 41 42 ClassFile cf = ClassFile.read(classFile); 43 test(cf); 44 for (Field f : cf.fields) { 45 test(cf, f); 46 } 47 for (Method m: cf.methods) { 48 test(cf, m); 49 } 50 51 // counts are zero when vising outer class 52 countAnnotations(0); 53 54 // visit inner class 55 File innerFile = new File("Test$1Inner.class"); 56 ClassFile icf = ClassFile.read(innerFile); 57 test(icf); 58 for (Field f : icf.fields) { 59 test(cf, f); 60 } 61 for (Method m: icf.methods) { 62 test(cf, m); 63 } 64 65 countAnnotations(1); 66 if (errors > 0) 67 throw new Exception(errors + " errors found"); 68 System.out.println("PASSED"); 69 } 70 71 void test(ClassFile cf) { 72 test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); 73 test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); 74 } 75 76 void test(ClassFile cf, Method m) { 77 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 78 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 79 } 80 81 void test(ClassFile cf, Field m) { 82 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 83 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 84 } 85 86 // test the result of Attributes.getIndex according to expectations 87 // encoded in the method's name 88 void test(ClassFile cf, String name, boolean visible) { 89 int index = cf.attributes.getIndex(cf.constant_pool, name); 90 if (index != -1) { 91 Attribute attr = cf.attributes.get(index); 92 assert attr instanceof RuntimeTypeAnnotations_attribute; 93 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 94 all += tAttr.annotations.length; 95 if (visible) 96 visibles += tAttr.annotations.length; 97 else 98 invisibles += tAttr.annotations.length; 99 } 100 } 101 102 // test the result of Attributes.getIndex according to expectations 103 // encoded in the method's name 104 void test(ClassFile cf, Method m, String name, boolean visible) { 105 int index = m.attributes.getIndex(cf.constant_pool, name); 106 if (index != -1) { 107 Attribute attr = m.attributes.get(index); 108 assert attr instanceof RuntimeTypeAnnotations_attribute; 109 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 110 all += tAttr.annotations.length; 111 if (visible) 112 visibles += tAttr.annotations.length; 113 else 114 invisibles += tAttr.annotations.length; 115 } 116 } 117 118 // test the result of Attributes.getIndex according to expectations 119 // encoded in the method's name 120 void test(ClassFile cf, Field m, String name, boolean visible) { 121 int index = m.attributes.getIndex(cf.constant_pool, name); 122 if (index != -1) { 123 Attribute attr = m.attributes.get(index); 124 assert attr instanceof RuntimeTypeAnnotations_attribute; 125 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 126 all += tAttr.annotations.length; 127 if (visible) 128 visibles += tAttr.annotations.length; 129 else 130 invisibles += tAttr.annotations.length; 131 } 132 } 133 134 File writeTestFile() throws IOException { 135 File f = new File("Test.java"); 136 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); 137 138 out.println("import java.lang.annotation.*;"); 139 out.println("class Test {"); 140 out.println(" void method() {"); 141 out.println(" class Inner<T extends @A Object> { }"); 142 out.println(" }"); 143 out.println("}"); 144 out.println("@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); 145 out.println("@interface A { }"); 146 out.close(); 147 System.out.println(f.getAbsolutePath()); 148 return f; 149 } 150 151 File compileTestFile(File f) { 152 int rc = com.sun.tools.javac.Main.compile(new String[] {"-g", f.getPath() }); 153 if (rc != 0) 154 throw new Error("compilation failed. rc=" + rc); 155 String path = f.getPath(); 156 return new File(path.substring(0, path.length() - 5) + ".class"); 157 } 158 159 void countAnnotations(int expected_invisibles) { 160 int expected_visibles = 0; 161 int expected_all = expected_visibles + expected_invisibles; 162 163 if (expected_all != all) { 164 errors++; 165 System.err.println("expected " + expected_all 166 + " annotations but found " + all); 167 } 168 169 if (expected_visibles != visibles) { 170 errors++; 171 System.err.println("expected " + expected_visibles 172 + " visibles annotations but found " + visibles); 173 } 174 175 if (expected_invisibles != invisibles) { 176 errors++; 177 System.err.println("expected " + expected_invisibles 178 + " invisibles annotations but found " + invisibles); 179 } 180 181 } 182 183 int errors; 184 int all; 185 int visibles; 186 int invisibles; 187 }