/* * Copyright (c) 2013 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. */ /* * @test * @bug 8006507 * @summary Annotations on methods in anonymous class written incorrectly to classfile. */ import java.lang.annotation.*; import java.io.*; import java.net.URL; import java.util.List; import java.util.Map; import java.util.HashMap; import com.sun.tools.classfile.*; import java.lang.annotation.*; import static java.lang.annotation.RetentionPolicy.*; import static java.lang.annotation.ElementType.*; public class TestAnonInnerMethod { int texpected = 0, // expected RuntimeTypeAnnotations expected = 0, // expected RuntimeAnnotations all = 0, // all RuntimeAnnotations, should be 0 allt=0, // all RuntimeTypeAnnotations failures = 0; public static void main(String[] args) throws Exception { new TestAnonInnerMethod().run(); } void report(String d) { int fail=0; if(texpected != allt) { System.out.println("Failed: " + d + "\n Expected " + texpected + " RuntimeTypeAnnotations, but got " + allt); fail++; } if(expected != all) { System.out.println("Failed: " + d + "\n Expected " + texpected + " RuntimeAnnotations, but got " + allt); fail++; } failures+=fail; if(fail==0) System.out.println("Pass: " + d); System.out.println(); } void test(int TExpected, int Expected, ClassFile cf, Method m, Field f, String name) { boolean isTAattr = name.contains("TypeAnnotations"); expected = Expected; texpected = TExpected; all = 0; allt=0; int index = 0; Attribute attr = null; index = m.attributes.getIndex(cf.constant_pool, name); String testDescription=""; if(index != -1) { attr = m.attributes.get(index); if(isTAattr) { //count RuntimeTypeAnnotations RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr; try{ System.out.println("Class: " + cf.getName()); testDescription="METHOD: " + m.getName(cf.constant_pool) + ", " + name + ": " + tAttr.annotations.length; } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } allt += tAttr.annotations.length; } else { //count RuntimeAnnotations RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr; try{ System.out.println("Class: " + cf.getName()); testDescription="METHOD: " + m.getName(cf.constant_pool) + ", " + name + ": " + tAttr.annotations.length; } catch(ConstantPoolException cpe) { cpe.printStackTrace(); } all += tAttr.annotations.length; } report(testDescription); } } public void run() { ClassFile cf = null; InputStream in = null; System.out.println("Test1: basic annotated method in a class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(1,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,1,cf, m, null, Attribute.RuntimeVisibleAnnotations); } System.out.println("Test2: annotated method in anonymous class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass$1.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(1,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,1,cf, m, null, Attribute.RuntimeVisibleAnnotations); } System.out.println("Test3: Two annotations on method in class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass2.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(2,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,2,cf, m, null, Attribute.RuntimeVisibleAnnotations); } System.out.println("Test4: Two annotations on method in anonymous class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass2$1.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(2,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,2,cf, m, null, Attribute.RuntimeVisibleAnnotations); } System.out.println("Test5: Repeated annotation on method in class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass3.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(1,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,1,cf, m, null, Attribute.RuntimeVisibleAnnotations); } System.out.println("Test6: Repeated annotation on method in anonymous class"); try { in = getClass().getResource("TestAnonInnerMethod$testclass3$1.class").openStream(); cf = ClassFile.read(in); in.close(); } catch(Exception e) { e.printStackTrace(); } for (Method m: cf.methods) { test(1,0,cf, m, null, Attribute.RuntimeVisibleTypeAnnotations); test(0,1,cf, m, null, Attribute.RuntimeVisibleAnnotations); } if(failures>0) { System.out.println("There were " + failures + " failures."); throw new RuntimeException("There were " + failures + " failures."); } } //////// test sources ////////////////////////// // Tests 1 & 2 class testclass { @C String m1(){return null;}; void mtest( testclass t){ } public void test() { mtest( new testclass() { @D String m2(){return null;}; }); } } // Tests 3 & 4 class testclass2 { @A @B String m1(){return null;}; void mtest( testclass t){ } public void test() { mtest( new testclass() { @A @B String m2(){return null;}; }); } } // Tests 5 & 6 class testclass3 { @A @A String m1(){return null;}; void mtest( testclass t){ } public void test() { mtest( new testclass() { @A @A String m2(){return null;}; }); } } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @Repeatable( AC.class ) @interface A { } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface AC { A[] value(); } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @Repeatable( BC.class ) @interface B { } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface BC { B[] value(); } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface C { } @Retention(RUNTIME) @Target({TYPE_USE,METHOD}) @interface D { } }