1 /* *******************************************************************
2 * Copyright (c) 2004 IBM
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Andy Clement - initial implementation
11 * ******************************************************************/
13 package org.aspectj.apache.bcel.classfile.tests;
16 import java.io.IOException;
17 import java.util.Iterator;
18 import java.util.List;
20 import org.aspectj.apache.bcel.classfile.Attribute;
21 import org.aspectj.apache.bcel.classfile.ConstantPool;
22 import org.aspectj.apache.bcel.classfile.JavaClass;
23 import org.aspectj.apache.bcel.classfile.Utility;
24 import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValueGen;
25 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
26 import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen;
27 import org.aspectj.apache.bcel.classfile.annotation.ClassElementValueGen;
28 import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
29 import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
30 import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen;
31 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
32 import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValueGen;
33 import org.aspectj.apache.bcel.generic.ClassGen;
34 import org.aspectj.apache.bcel.util.SyntheticRepository;
37 public class RuntimeVisibleAnnotationAttributeTest extends BcelTestCase {
40 protected void setUp() throws Exception {
44 public void testSeeAnnotationsAsAttribute() throws ClassNotFoundException {
45 SyntheticRepository repos = createRepos("testcode.jar");
46 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
47 ConstantPool pool = clazz.getConstantPool();
48 Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
49 assertTrue("Expected a RuntimeVisibleAnnotations attribute but found none",
53 public void testAnnotationsAttributeContainsRightData() throws ClassNotFoundException {
54 SyntheticRepository repos = createRepos("testcode.jar");
55 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
56 ConstantPool pool = clazz.getConstantPool();
57 Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
58 RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) rvaAttr[0];
59 List anns = rva.getAnnotations();
60 assertTrue("Should be one annotation but found "+anns.size(),
62 AnnotationGen ann = (AnnotationGen) anns.get(0);
63 assertTrue("Should be called 'SimpleAnnotation' but was called "+ann.getTypeName(),
64 ann.getTypeName().equals("SimpleAnnotation"));
65 List l = ann.getValues();
66 assertTrue("Should be one value for annotation 'SimpleAnnotation' but found "+l.size(),
68 ElementNameValuePairGen envp = (ElementNameValuePairGen)l.get(0);
69 assertTrue("Name of element in SimpleAnnotation should be 'id' but it is "+envp.getNameString(),
70 envp.getNameString().equals("id"));
71 SimpleElementValueGen evalue = (SimpleElementValueGen)envp.getValue();
72 assertTrue("'id' should be of type int, but it is "+evalue.getElementValueType(),evalue.getElementValueType()==SimpleElementValueGen.PRIMITIVE_INT);
73 assertTrue("'id' should have value 4 but it is "+evalue.getValueInt(),
74 evalue.getValueInt()==4);
77 public void testAccessingAnnotationsOnClazz() throws ClassNotFoundException {
78 SyntheticRepository repos = createRepos("testcode.jar");
79 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
80 ConstantPool pool = clazz.getConstantPool();
81 AnnotationGen[] anns = clazz.getAnnotations();
82 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
86 public void testReadingWritingAnnotations() throws ClassNotFoundException, IOException {
87 SyntheticRepository repos = createRepos("testcode.jar");
88 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
89 ConstantPool pool = clazz.getConstantPool();
90 AnnotationGen[] anns = clazz.getAnnotations();
91 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
95 File tfile = createTestdataFile("SimpleAnnotatedClass.class");
98 SyntheticRepository repos2 = createRepos(".");
99 JavaClass clazz2 = repos.loadClass("SimpleAnnotatedClass");
100 ConstantPool pool2 = clazz2.getConstantPool();
101 AnnotationGen[] anns2 = clazz2.getAnnotations();
102 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns2.length,
105 assertTrue(tfile.delete());
111 // Test for annotations containing string elements
113 public void testAnnotationStringElement() throws ClassNotFoundException {
114 SyntheticRepository repos = createRepos("testcode.jar");
115 JavaClass clazz = repos.loadClass("AnnotatedClass");
116 verifyAnnotationStringElement(clazz);
120 public void testAnnotationStringElementReadWrite() throws ClassNotFoundException, IOException {
121 SyntheticRepository repos = createRepos("testcode.jar");
122 JavaClass clazz = repos.loadClass("AnnotatedClass");
123 verifyAnnotationStringElement(clazz);
126 File tfile = createTestdataFile("AnnotatedClass.class");
129 SyntheticRepository repos2 = createRepos(".");
130 JavaClass clazz2 = repos2.loadClass("AnnotatedClass");
131 verifyAnnotationStringElement(clazz2);
133 assertTrue(tfile.delete());
136 private void verifyAnnotationStringElement(JavaClass clazz) {
137 AnnotationGen[] anns = clazz.getAnnotations();
138 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
139 AnnotationGen ann = anns[0];
140 assertTrue("should be called 'AnnotationStringElement' but was called "+ann.getTypeName(),
141 ann.getTypeName().equals("AnnotationStringElement"));
142 List l = ann.getValues();
143 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
144 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
145 assertTrue("Name of element should be 'stringval' but was "+nvp.getNameString(),
146 nvp.getNameString().equals("stringval"));
147 SimpleElementValueGen ev = (SimpleElementValueGen)nvp.getValue();
148 assertTrue("String value should be 'hello' but was '"+ev.getValueString()+"'",
149 ev.getValueString().equals("hello"));
153 // Test for complex annotation that includes all primitives
155 public void testComplexAnnotation() throws ClassNotFoundException {
156 SyntheticRepository repos = createRepos("testcode.jar");
157 JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
158 verifyComplexAnnotation(clazz);
162 public void testComplexAnnotationsReadWrite() throws ClassNotFoundException, IOException {
163 SyntheticRepository repos = createRepos("testcode.jar");
164 JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
165 verifyComplexAnnotation(clazz);
168 File tfile = createTestdataFile("ComplexAnnotatedClass.class");
171 SyntheticRepository repos2 = createRepos(".");
172 JavaClass clazz2 = repos.loadClass("ComplexAnnotatedClass");
173 verifyComplexAnnotation(clazz2);
175 assertTrue(tfile.delete());
179 private void verifyComplexAnnotation(JavaClass clazz) {
180 AnnotationGen[] anns = clazz.getAnnotations();
181 assertTrue("Should be one annotation but found "+anns.length,anns.length==1);
182 AnnotationGen ann = anns[0];
183 assertTrue("Should be called 'ComplexAnnotation' but was called "+ann.getTypeName(),
184 ann.getTypeName().equals("ComplexAnnotation"));
185 List l = ann.getValues();
186 assertTrue("Should be eight values for annotation 'ComplexAnnotation' but found "+l.size(),
188 List names = Utility.getListOfAnnotationNames(ann);
189 assertTrue("Cant find expected element ",names.contains("ival"));
190 assertTrue("Cant find expected element ",names.contains("dval"));
191 assertTrue("Cant find expected element ",names.contains("zval"));
192 assertTrue("Cant find expected element ",names.contains("fval"));
193 assertTrue("Cant find expected element ",names.contains("jval"));
194 assertTrue("Cant find expected element ",names.contains("sval"));
195 assertTrue("Cant find expected element ",names.contains("bval"));
196 assertTrue("Cant find expected element ",names.contains("cval"));
198 checkValue(ann,"ival","4");
199 checkValue(ann,"jval","56");
200 checkValue(ann,"fval","3.0");
201 checkValue(ann,"dval","33.4");
202 checkValue(ann,"sval","99");
203 checkValue(ann,"bval","2");
204 checkValue(ann,"cval",new Character('5').toString());
205 checkValue(ann,"zval","false");
209 private void checkValue(AnnotationGen a,String name,String tostring) {
210 for (Iterator i = a.getValues().iterator(); i.hasNext();) {
211 ElementNameValuePairGen element = (ElementNameValuePairGen) i.next();
212 if (element.getNameString().equals(name)) {
213 if (!element.getValue().stringifyValue().equals(tostring)) {
214 fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
219 fail("Didnt find named element "+name);
223 // Test an annotation containing a 'Class' element
225 public void testAnnotationClassElement() throws ClassNotFoundException {
226 SyntheticRepository repos = createRepos("testcode.jar");
227 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
228 verifyClassAnnotation(clazz);
231 public void testAnnotationClassElementCopying() throws ClassNotFoundException {
232 SyntheticRepository repos = createRepos("testcode.jar");
233 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
234 AnnotationGen[] anns = clazz.getAnnotations();
235 ClassGen cg = new ClassGen(clazz);
236 // Checks we can copy class values in an annotation
237 new AnnotationGen(anns[0],cg.getConstantPool(),true);
238 new AnnotationGen(anns[0],cg.getConstantPool(),false);
241 public void testAnnotationClassElementReadWrite() throws ClassNotFoundException,IOException {
242 SyntheticRepository repos = createRepos("testcode.jar");
243 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
244 verifyClassAnnotation(clazz);
247 File tfile = createTestdataFile("AnnotatedWithClassClass.class");
250 SyntheticRepository repos2 = createRepos(".");
251 JavaClass clazz2 = repos2.loadClass("AnnotatedWithClassClass");
252 verifyClassAnnotation(clazz2);
254 assertTrue(wipe("AnnotatedWithClassClass.class"));
257 private void verifyClassAnnotation(JavaClass clazz) {
258 AnnotationGen[] anns = clazz.getAnnotations();
259 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
260 AnnotationGen ann = anns[0];
261 assertTrue("should be called 'AnnotationClassElement' but was called "+ann.getTypeName(),
262 ann.getTypeName().equals("AnnotationClassElement"));
263 List l = ann.getValues();
264 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
265 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
266 assertTrue("Name of element should be 'clz' but was "+nvp.getNameString(),
267 nvp.getNameString().equals("clz"));
268 ClassElementValueGen ev = (ClassElementValueGen)nvp.getValue();
269 assertTrue("String value should be 'Ljava/lang/Integer;' but was '"+ev.getClassString()+"'",
270 ev.getClassString().equals("Ljava/lang/Integer;"));
275 // Test an annotation containing an enum element
277 public void testAnnotationEnumElement() throws ClassNotFoundException {
278 SyntheticRepository repos = createRepos("testcode.jar");
279 JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
280 verifyAnnotationEnumElement(clazz);
283 public void testAnnotationEnumElementReadWrite() throws ClassNotFoundException, IOException {
284 SyntheticRepository repos = createRepos("testcode.jar");
285 JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
286 verifyAnnotationEnumElement(clazz);
289 File tfile = createTestdataFile("AnnotatedWithEnumClass.class");
292 SyntheticRepository repos2 = createRepos(".");
293 JavaClass clazz2 = repos2.loadClass("AnnotatedWithEnumClass");
294 verifyAnnotationEnumElement(clazz2);
296 assertTrue(tfile.delete());
299 public void verifyAnnotationEnumElement(JavaClass clazz) {
300 AnnotationGen[] anns = clazz.getAnnotations();
301 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
302 AnnotationGen ann = anns[0];
303 assertTrue("should be called 'AnnotationEnumElement' but was called "+ann.getTypeName(),
304 ann.getTypeName().equals("AnnotationEnumElement"));
305 List l = ann.getValues();
306 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
307 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
308 assertTrue("Name of element should be 'enumval' but was "+nvp.getNameString(),
309 nvp.getNameString().equals("enumval"));
310 ElementValueGen ev = nvp.getValue();
311 assertTrue("Should be of type EnumElementValue but is "+ev,ev instanceof EnumElementValueGen);
312 EnumElementValueGen eev = (EnumElementValueGen)ev;
313 assertTrue("Should be an enum type value but is "+eev.getElementValueType(),eev.getElementValueType()==SimpleElementValueGen.ENUM_CONSTANT);
314 assertTrue("Enum type for annotation should be 'SimpleEnum' but is "+Utility.signatureToString(eev.getEnumTypeString()),Utility.signatureToString(eev.getEnumTypeString()).equals("SimpleEnum"));
315 assertTrue("String value should be 'Red' but was '"+eev.getEnumValueString()+"'",
316 eev.getEnumValueString().equals("Red"));
320 // Test an annotation with an array element
322 public void testAnnotationArraysOfAnnotations() throws ClassNotFoundException {
323 SyntheticRepository repos = createRepos("testcode.jar");
324 JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
325 AnnotationGen[] anns = clazz.getAnnotations();
326 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
327 checkCombinedAnnotation(anns[0]);
330 public void testAnnotationArraysOfAnnotationsReadWrite() throws ClassNotFoundException, IOException {
331 SyntheticRepository repos = createRepos("testcode.jar");
332 JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
333 AnnotationGen[] anns = clazz.getAnnotations();
334 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
335 checkCombinedAnnotation(anns[0]);
338 File tfile = createTestdataFile("AnnotatedWithCombinedAnnotation.class");
341 SyntheticRepository repos2 = createRepos(".");
342 JavaClass clazz2 = repos2.loadClass("AnnotatedWithCombinedAnnotation");
343 AnnotationGen[] anns2 = clazz2.getAnnotations();
344 assertTrue("should be one annotation but found "+anns2.length,anns2.length==1);
345 checkCombinedAnnotation(anns2[0]);
347 assertTrue(tfile.delete());
351 private void checkCombinedAnnotation(AnnotationGen ann) {
352 assertTrue("should be called 'CombinedAnnotation' but was called "+ann.getTypeName(),
353 ann.getTypeName().equals("CombinedAnnotation"));
354 List l = ann.getValues();
355 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
356 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
357 assertTrue("Name of element should be 'value' but was "+nvp.getNameString(),
358 nvp.getNameString().equals("value"));
359 ElementValueGen ev = nvp.getValue();
360 assertTrue("Should be of type ArrayElementValue but is "+ev,ev instanceof ArrayElementValueGen);
361 ArrayElementValueGen aev = (ArrayElementValueGen)ev;
363 assertTrue("Array element value should be of size 1 but is "+aev.getElementValuesArraySize(),
364 aev.getElementValuesArraySize()==1);
365 ElementValueGen[] evs = aev.getElementValuesArray();
366 assertTrue("Entry in the array should be AnnotationElementValue but is "+evs[0],
367 evs[0] instanceof AnnotationElementValueGen);
368 AnnotationElementValueGen inner_ev = (AnnotationElementValueGen)evs[0];
369 AnnotationGen a = inner_ev.getAnnotation();
370 assertTrue("Should be SimpleAnnotation but is "+a.getTypeName(),a.getTypeName().equals("SimpleAnnotation"));
371 List envps = a.getValues();
372 assertTrue("Should be one name value pair but found "+envps.size(),envps.size()==1);
373 ElementNameValuePairGen envp = (ElementNameValuePairGen) envps.get(0);
374 assertTrue("Name should be 'id' but it is "+envp.getNameString(),envp.getNameString().equals("id"));
375 assertTrue("Value of 'id' should be 4 but it is "+envp.getValue().stringifyValue(),
376 envp.getValue().stringifyValue().equals("4"));
380 protected void tearDown() throws Exception {