1 /*
2  * Copyright (c) 2006, 2018, 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 /*
25  * @test
26  * @bug 5002251 6407335 6412391
27  * @summary Redefine a class that has an annotation and verify that the
28  * new annotation is returned.
29  * @comment converted from test/jdk/com/sun/jdi/RedefineAnnotation.sh
30  *
31  * @library /test/lib
32  * @compile -g RedefineAnnotation.java
33  * @run main/othervm RedefineAnnotation
34  */
35 
36 import jdk.test.lib.process.OutputAnalyzer;
37 import lib.jdb.JdbCommand;
38 import lib.jdb.JdbTest;
39 
40 import java.lang.annotation.*;
41 import java.lang.reflect.*;
42 
43 @Foo(Constants.class_annotation)  // @1 commentout
44 // @1 uncomment @Foo(Constants.new_class_annotation)
45 class RedefineAnnotationTarg {
46     @Foo(Constants.field_annotation)  // @1 commentout
47     // @1 uncomment @Foo(Constants.new_field_annotation)
48     public int dummy_field;
49 
main(String[] args)50     public static void main(String[] args) {
51         MySubClass sub = new MySubClass();
52         MySubSubClass subsub = new MySubSubClass();
53         new RedefineAnnotationTarg().hi(false);
54         new RedefineAnnotationTarg().hi(true);  // @1 breakpoint
55         sub.hi(true);
56         subsub.hi(true);
57     }
58 
59     @Foo(Constants.method_annotation)  // @1 commentout
60     // @1 uncomment @Foo(Constants.new_method_annotation)
hi( @ooConstants.method_parameter_annotation) boolean isNewVersion)61     public void hi(
62     @Foo(Constants.method_parameter_annotation)  // @1 commentout
63     // @1 uncomment @Foo(Constants.new_method_parameter_annotation)
64                    boolean isNewVersion) {
65 
66         if (isNewVersion) {
67             System.out.println("Checking for NEW versions of annotations in "
68                 + getClass());
69         }
70 
71         // class annotations check:
72         Foo foo = getClass().getAnnotation(Foo.class);
73         if (foo == null) {
74           throw new Error("FAIL: cannot get class_annotation from "
75                         + getClass());
76         }
77 
78         String class_annotation = foo.value();
79         System.out.println("class annotation is: " + class_annotation);
80         if (isNewVersion) {
81             if (class_annotation.equals(Constants.new_class_annotation)) {
82                 System.out.println("PASS: class_annotation was changed.");
83             } else {
84                 System.out.println("FAIL: class_annotation was NOT changed.");
85             }
86         }
87 
88         // field annotations check:
89         try {
90             Field my_field = getClass().getField("dummy_field");
91             foo = my_field.getAnnotation(Foo.class);
92             if (foo == null) {
93               throw new Error("FAIL: cannot get field_annotation from "
94                             + getClass() + ".dummy_field");
95             }
96             String field_annotation = foo.value();
97             System.out.println("field annotation is: " + field_annotation);
98             if (isNewVersion) {
99                 if (field_annotation.equals(Constants.new_field_annotation)) {
100                     System.out.println("PASS: field_annotation was changed.");
101                 } else {
102                     System.out.println(
103                         "FAIL: field_annotation was NOT changed.");
104                 }
105         }
106         } catch (NoSuchFieldException nsfe) {
107             throw new Error("FAIL: cannot find field 'dummy_field' in "
108                           + getClass());
109         }
110 
111         // method annotations check:
112         try {
113             Class params[] = new Class[1];
114             params[0] = Boolean.TYPE;
115             Method my_method = getClass().getMethod("hi", params);
116             foo = my_method.getAnnotation(Foo.class);
117             if (foo == null) {
118               throw new Error("FAIL: cannot get field_annotation from "
119                             + getClass() + ".hi()");
120             }
121             String method_annotation = foo.value();
122             System.out.println("method annotation is: " + method_annotation);
123             if (isNewVersion) {
124                 if (method_annotation.equals(Constants.new_method_annotation)) {
125                     System.out.println("PASS: method_annotation was changed.");
126                 } else {
127                     System.out.println(
128                         "FAIL: method_annotation was NOT changed.");
129                 }
130             }
131         } catch (NoSuchMethodException nsme) {
132             throw new Error("FAIL: cannot find method 'hi' in " + getClass());
133         }
134 
135         // method parameter annotations check:
136         try {
137             Class params[] = new Class[1];
138             params[0] = Boolean.TYPE;
139             Method my_method = getClass().getMethod("hi", params);
140             Annotation my_annotations[][] = my_method.getParameterAnnotations();
141             if (my_annotations.length != 1) {
142                 throw new Error("FAIL: unexpected my_annotations.length ("
143                               + my_annotations.length);
144             }
145             Annotation my_annotation[] = my_annotations[0];
146             if (my_annotation.length != 1) {
147                 throw new Error("FAIL: unexpected my_annotation.length ("
148                               + my_annotation.length);
149             }
150             foo = (Foo)my_annotation[0];
151             String method_parameter_annotation = foo.value();
152             System.out.println("method parameter annotation is: "
153                 + method_parameter_annotation);
154             if (isNewVersion) {
155                 if (method_parameter_annotation.equals(
156                     Constants.new_method_parameter_annotation)) {
157                     System.out.println(
158                         "PASS: method_parameter_annotation was changed.");
159                 } else {
160                     System.out.println(
161                         "FAIL: method_parameter_annotation was NOT changed.");
162                 }
163             }
164         } catch (NoSuchMethodException nsme) {
165             throw new Error("FAIL: cannot find method 'hi' in " + getClass());
166         }
167     }
168 }
169 
170 // this subclass exists just to make the RedefineClasses() code do a
171 // subclass walk to update the counter
172 class MySubClass extends RedefineAnnotationTarg {
173     int my_int_field_makes_me_different;
174 }
175 
176 // this subclass exists just to make the RedefineClasses() code do a
177 // sub-subclass walk to update the counter
178 class MySubSubClass extends MySubClass {
179     float my_float_field_makes_me_different;
180 }
181 
182 class Constants {
183     static final String class_annotation     = "Patrick's class comment";
184     static final String new_class_annotation = "*NEW* Patrick's class comment";
185 
186     static final String field_annotation     = "dummy_field comment";
187     static final String new_field_annotation = "*NEW* dummy_field comment";
188 
189     static final String method_annotation     = "method hi() comment";
190     static final String new_method_annotation = "*NEW* method hi() comment";
191 
192     static final String method_parameter_annotation     =
193         "param isNewVersion comment";
194     static final String new_method_parameter_annotation =
195         "*NEW* param isNewVersion comment";
196 }
197 
198 
199 /**
200  */
201 @Retention(RetentionPolicy.RUNTIME)
202 @Inherited
203 @interface Foo {
value()204     String value();
205 }
206 
207 public class RedefineAnnotation extends JdbTest {
208 
main(String argv[])209     public static void main(String argv[]) {
210         new RedefineAnnotation().run();
211     }
212 
RedefineAnnotation()213     private RedefineAnnotation() {
214         super(DEBUGGEE_CLASS, SOURCE_FILE);
215     }
216 
217     private static final String DEBUGGEE_CLASS = RedefineAnnotationTarg.class.getName();
218     private static final String SOURCE_FILE = "RedefineAnnotation.java";
219 
220     @Override
runCases()221     protected void runCases() {
222         setBreakpoints(1);
223         jdb.command(JdbCommand.run());
224 
225         redefineClass(1, "-g");
226         jdb.contToExit(1);
227 
228         new OutputAnalyzer(getDebuggeeOutput())
229                 .shouldNotContain("FAIL:");
230     }
231 }
232