1 /* 2 * Copyright (c) 2009, 2015, 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 * @modules jdk.jdeps/com.sun.tools.classfile 32 */ 33 34 public class PresenceInner { 35 public static void main(String[] args) throws Exception { 36 new PresenceInner().run(); 37 } 38 39 public void run() throws Exception { 40 File javaFile = writeTestFile(); 41 File classFile = compileTestFile(javaFile); 42 43 ClassFile cf = ClassFile.read(classFile); 44 test(cf); 45 for (Field f : cf.fields) { 46 test(cf, f); 47 } 48 for (Method m: cf.methods) { 49 test(cf, m); 50 } 51 52 // counts are zero when vising outer class 53 countAnnotations(0); 54 55 // visit inner class 56 File innerFile = new File("Test$1Inner.class"); 57 ClassFile icf = ClassFile.read(innerFile); 58 test(icf); 59 for (Field f : icf.fields) { 60 test(cf, f); 61 } 62 for (Method m: icf.methods) { 63 test(cf, m); 64 } 65 66 countAnnotations(1); 67 if (errors > 0) 68 throw new Exception(errors + " errors found"); 69 System.out.println("PASSED"); 70 } 71 72 void test(ClassFile cf) { 73 test(cf, Attribute.RuntimeVisibleTypeAnnotations, true); 74 test(cf, Attribute.RuntimeInvisibleTypeAnnotations, false); 75 } 76 77 void test(ClassFile cf, Method m) { 78 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 79 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 80 } 81 82 void test(ClassFile cf, Field m) { 83 test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true); 84 test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false); 85 } 86 87 // test the result of Attributes.getIndex according to expectations 88 // encoded in the method's name 89 void test(ClassFile cf, String name, boolean visible) { 90 int index = cf.attributes.getIndex(cf.constant_pool, name); 91 if (index != -1) { 92 Attribute attr = cf.attributes.get(index); 93 assert attr instanceof RuntimeTypeAnnotations_attribute; 94 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 95 all += tAttr.annotations.length; 96 if (visible) 97 visibles += tAttr.annotations.length; 98 else 99 invisibles += tAttr.annotations.length; 100 } 101 } 102 103 // test the result of Attributes.getIndex according to expectations 104 // encoded in the method's name 105 void test(ClassFile cf, Method m, String name, boolean visible) { 106 int index = m.attributes.getIndex(cf.constant_pool, name); 107 if (index != -1) { 108 Attribute attr = m.attributes.get(index); 109 assert attr instanceof RuntimeTypeAnnotations_attribute; 110 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 111 all += tAttr.annotations.length; 112 if (visible) 113 visibles += tAttr.annotations.length; 114 else 115 invisibles += tAttr.annotations.length; 116 } 117 } 118 119 // test the result of Attributes.getIndex according to expectations 120 // encoded in the method's name 121 void test(ClassFile cf, Field m, String name, boolean visible) { 122 int index = m.attributes.getIndex(cf.constant_pool, name); 123 if (index != -1) { 124 Attribute attr = m.attributes.get(index); 125 assert attr instanceof RuntimeTypeAnnotations_attribute; 126 RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; 127 all += tAttr.annotations.length; 128 if (visible) 129 visibles += tAttr.annotations.length; 130 else 131 invisibles += tAttr.annotations.length; 132 } 133 } 134 135 File writeTestFile() throws IOException { 136 File f = new File("Test.java"); 137 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); 138 139 out.println("import java.lang.annotation.*;"); 140 out.println("class Test {"); 141 out.println(" void method() {"); 142 out.println(" class Inner<T extends @A Object> { }"); 143 out.println(" }"); 144 out.println("}"); 145 out.println("@Target({ElementType.TYPE_USE, ElementType.TYPE_PARAMETER})"); 146 out.println("@interface A { }"); 147 out.close(); 148 System.out.println(f.getAbsolutePath()); 149 return f; 150 } 151 152 File compileTestFile(File f) { 153 int rc = com.sun.tools.javac.Main.compile(new String[] {"-g", f.getPath() }); 154 if (rc != 0) 155 throw new Error("compilation failed. rc=" + rc); 156 String path = f.getPath(); 157 return new File(path.substring(0, path.length() - 5) + ".class"); 158 } 159 160 void countAnnotations(int expected_invisibles) { 161 int expected_visibles = 0; 162 int expected_all = expected_visibles + expected_invisibles; 163 164 if (expected_all != all) { 165 errors++; 166 System.err.println("expected " + expected_all 167 + " annotations but found " + all); 168 } 169 170 if (expected_visibles != visibles) { 171 errors++; 172 System.err.println("expected " + expected_visibles 173 + " visibles annotations but found " + visibles); 174 } 175 176 if (expected_invisibles != invisibles) { 177 errors++; 178 System.err.println("expected " + expected_invisibles 179 + " invisibles annotations but found " + invisibles); 180 } 181 182 } 183 184 int errors; 185 int all; 186 int visibles; 187 int invisibles; 188 }