1/*
2 * Copyright (c) 2008, 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
24import java.io.*;
25import java.lang.annotation.Retention;
26import java.lang.annotation.RetentionPolicy;
27import java.net.URL;
28import java.util.List;
29
30import com.sun.tools.classfile.*;
31
32/*
33 * @test NoTargetAnnotations
34 * @summary test that annotations with no Target meta type is emitted
35 *          only once as declaration annotation
36 * @modules jdk.jdeps/com.sun.tools.classfile
37 */
38public class NoTargetAnnotations {
39
40    public static void main(String[] args) throws Exception {
41        new NoTargetAnnotations().run();
42    }
43
44    public void run() throws Exception {
45        ClassFile cf = getClassFile("NoTargetAnnotations$Test.class");
46        for (Field f : cf.fields) {
47            test(cf, f);
48            testDeclaration(cf, f);
49        }
50        for (Method m: cf.methods) {
51            test(cf, m);
52            testDeclaration(cf, m);
53        }
54
55        countAnnotations();
56
57        if (errors > 0)
58            throw new Exception(errors + " errors found");
59        System.out.println("PASSED");
60    }
61
62    ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
63        URL url = getClass().getResource(name);
64        InputStream in = url.openStream();
65        try {
66            return ClassFile.read(in);
67        } finally {
68            in.close();
69        }
70    }
71
72    /************ Helper annotations counting methods ******************/
73    void test(ClassFile cf, Method m) {
74        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
75        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
76    }
77
78    void test(ClassFile cf, Field m) {
79        test(cf, m, Attribute.RuntimeVisibleTypeAnnotations, true);
80        test(cf, m, Attribute.RuntimeInvisibleTypeAnnotations, false);
81    }
82
83    void testDeclaration(ClassFile cf, Method m) {
84        testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true);
85        testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false);
86    }
87
88    void testDeclaration(ClassFile cf, Field m) {
89        testDecl(cf, m, Attribute.RuntimeVisibleAnnotations, true);
90        testDecl(cf, m, Attribute.RuntimeInvisibleAnnotations, false);
91    }
92
93    // test the result of Attributes.getIndex according to expectations
94    // encoded in the method's name
95    void test(ClassFile cf, Method m, String name, boolean visible) {
96        int index = m.attributes.getIndex(cf.constant_pool, name);
97        if (index != -1) {
98            Attribute attr = m.attributes.get(index);
99            assert attr instanceof RuntimeTypeAnnotations_attribute;
100            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
101            all += tAttr.annotations.length;
102            if (visible)
103                visibles += tAttr.annotations.length;
104            else
105                invisibles += tAttr.annotations.length;
106        }
107    }
108
109    // test the result of Attributes.getIndex according to expectations
110    // encoded in the method's name
111    void test(ClassFile cf, Field m, String name, boolean visible) {
112        int index = m.attributes.getIndex(cf.constant_pool, name);
113        if (index != -1) {
114            Attribute attr = m.attributes.get(index);
115            assert attr instanceof RuntimeTypeAnnotations_attribute;
116            RuntimeTypeAnnotations_attribute tAttr = (RuntimeTypeAnnotations_attribute)attr;
117            all += tAttr.annotations.length;
118            if (visible)
119                visibles += tAttr.annotations.length;
120            else
121                invisibles += tAttr.annotations.length;
122        }
123    }
124
125    // test the result of Attributes.getIndex according to expectations
126    // encoded in the method's name
127    void testDecl(ClassFile cf, Method m, String name, boolean visible) {
128        int index = m.attributes.getIndex(cf.constant_pool, name);
129        if (index != -1) {
130            Attribute attr = m.attributes.get(index);
131            assert attr instanceof RuntimeAnnotations_attribute;
132            RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr;
133            this.declAnnotations += tAttr.annotations.length;
134        }
135    }
136
137    // test the result of Attributes.getIndex according to expectations
138    // encoded in the method's name
139    void testDecl(ClassFile cf, Field m, String name, boolean visible) {
140        int index = m.attributes.getIndex(cf.constant_pool, name);
141        if (index != -1) {
142            Attribute attr = m.attributes.get(index);
143            assert attr instanceof RuntimeAnnotations_attribute;
144            RuntimeAnnotations_attribute tAttr = (RuntimeAnnotations_attribute)attr;
145            this.declAnnotations += tAttr.annotations.length;
146        }
147    }
148
149    File compileTestFile(File f) {
150        int rc = com.sun.tools.javac.Main.compile(new String[] { "-XDTA:writer", "-g", f.getPath() });
151        if (rc != 0)
152            throw new Error("compilation failed. rc=" + rc);
153        String path = f.getPath();
154        return new File(path.substring(0, path.length() - 5) + ".class");
155    }
156
157    void countAnnotations() {
158        int expected_all = expected_visibles + expected_invisibles;
159
160        if (expected_all != all) {
161            errors++;
162            System.err.println("expected " + expected_all
163                    + " annotations but found " + all);
164        }
165
166        if (expected_visibles != visibles) {
167            errors++;
168            System.err.println("expected " + expected_visibles
169                    + " visibles annotations but found " + visibles);
170        }
171
172        if (expected_invisibles != invisibles) {
173            errors++;
174            System.err.println("expected " + expected_invisibles
175                    + " invisibles annotations but found " + invisibles);
176        }
177
178        if (expected_decl != declAnnotations) {
179            errors++;
180            System.err.println("expected " + expected_decl
181                    + " declaration annotations but found " + declAnnotations);
182        }
183    }
184
185    int errors;
186    int all;
187    int visibles;
188    int invisibles;
189
190    int declAnnotations;
191
192    /*********************** Test class *************************/
193    static int expected_invisibles = 0;
194    static int expected_visibles = 0;
195    static int expected_decl = 1;
196
197    static class Test {
198        @Retention(RetentionPolicy.RUNTIME)
199        @interface A {}
200
201        @A String method() {
202            return null;
203        }
204    }
205}
206