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.ArrayList;
18 import java.util.Iterator;
19 import java.util.List;
21 import org.aspectj.apache.bcel.classfile.Attribute;
22 import org.aspectj.apache.bcel.classfile.ConstantPool;
23 import org.aspectj.apache.bcel.classfile.JavaClass;
24 import org.aspectj.apache.bcel.classfile.Utility;
25 import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValueGen;
26 import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
27 import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValueGen;
28 import org.aspectj.apache.bcel.classfile.annotation.ClassElementValueGen;
29 import org.aspectj.apache.bcel.classfile.annotation.ElementNameValuePairGen;
30 import org.aspectj.apache.bcel.classfile.annotation.ElementValueGen;
31 import org.aspectj.apache.bcel.classfile.annotation.EnumElementValueGen;
32 import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisibleAnnotations;
33 import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValueGen;
34 import org.aspectj.apache.bcel.generic.ClassGen;
35 import org.aspectj.apache.bcel.util.SyntheticRepository;
38 public class RuntimeVisibleAnnotationAttributeTest extends BcelTestCase {
41 protected void setUp() throws Exception {
45 public void testSeeAnnotationsAsAttribute() throws ClassNotFoundException {
46 SyntheticRepository repos = createRepos("testcode.jar");
47 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
48 ConstantPool pool = clazz.getConstantPool();
49 Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
50 assertTrue("Expected a RuntimeVisibleAnnotations attribute but found none",
54 public void testAnnotationsAttributeContainsRightData() throws ClassNotFoundException {
55 SyntheticRepository repos = createRepos("testcode.jar");
56 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
57 ConstantPool pool = clazz.getConstantPool();
58 Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
59 RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) rvaAttr[0];
60 List anns = rva.getAnnotations();
61 assertTrue("Should be one annotation but found "+anns.size(),
63 AnnotationGen ann = (AnnotationGen) anns.get(0);
64 assertTrue("Should be called 'SimpleAnnotation' but was called "+ann.getTypeName(),
65 ann.getTypeName().equals("SimpleAnnotation"));
66 List l = ann.getValues();
67 assertTrue("Should be one value for annotation 'SimpleAnnotation' but found "+l.size(),
69 ElementNameValuePairGen envp = (ElementNameValuePairGen)l.get(0);
70 assertTrue("Name of element in SimpleAnnotation should be 'id' but it is "+envp.getNameString(),
71 envp.getNameString().equals("id"));
72 SimpleElementValueGen evalue = (SimpleElementValueGen)envp.getValue();
73 assertTrue("'id' should be of type int, but it is "+evalue.getElementValueType(),evalue.getElementValueType()==SimpleElementValueGen.PRIMITIVE_INT);
74 assertTrue("'id' should have value 4 but it is "+evalue.getValueInt(),
75 evalue.getValueInt()==4);
78 public void testAccessingAnnotationsOnClazz() throws ClassNotFoundException {
79 SyntheticRepository repos = createRepos("testcode.jar");
80 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
81 ConstantPool pool = clazz.getConstantPool();
82 AnnotationGen[] anns = clazz.getAnnotations();
83 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
87 public void testReadingWritingAnnotations() throws ClassNotFoundException, IOException {
88 SyntheticRepository repos = createRepos("testcode.jar");
89 JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
90 ConstantPool pool = clazz.getConstantPool();
91 AnnotationGen[] anns = clazz.getAnnotations();
92 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
96 File tfile = createTestdataFile("SimpleAnnotatedClass.class");
99 SyntheticRepository repos2 = createRepos(".");
100 JavaClass clazz2 = repos.loadClass("SimpleAnnotatedClass");
101 ConstantPool pool2 = clazz2.getConstantPool();
102 AnnotationGen[] anns2 = clazz2.getAnnotations();
103 assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns2.length,
106 assertTrue(tfile.delete());
112 // Test for annotations containing string elements
114 public void testAnnotationStringElement() throws ClassNotFoundException {
115 SyntheticRepository repos = createRepos("testcode.jar");
116 JavaClass clazz = repos.loadClass("AnnotatedClass");
117 verifyAnnotationStringElement(clazz);
121 public void testAnnotationStringElementReadWrite() throws ClassNotFoundException, IOException {
122 SyntheticRepository repos = createRepos("testcode.jar");
123 JavaClass clazz = repos.loadClass("AnnotatedClass");
124 verifyAnnotationStringElement(clazz);
127 File tfile = createTestdataFile("AnnotatedClass.class");
130 SyntheticRepository repos2 = createRepos(".");
131 JavaClass clazz2 = repos2.loadClass("AnnotatedClass");
132 verifyAnnotationStringElement(clazz2);
134 assertTrue(tfile.delete());
137 private void verifyAnnotationStringElement(JavaClass clazz) {
138 AnnotationGen[] anns = clazz.getAnnotations();
139 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
140 AnnotationGen ann = anns[0];
141 assertTrue("should be called 'AnnotationStringElement' but was called "+ann.getTypeName(),
142 ann.getTypeName().equals("AnnotationStringElement"));
143 List l = ann.getValues();
144 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
145 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
146 assertTrue("Name of element should be 'stringval' but was "+nvp.getNameString(),
147 nvp.getNameString().equals("stringval"));
148 SimpleElementValueGen ev = (SimpleElementValueGen)nvp.getValue();
149 assertTrue("String value should be 'hello' but was '"+ev.getValueString()+"'",
150 ev.getValueString().equals("hello"));
154 // Test for complex annotation that includes all primitives
156 public void testComplexAnnotation() throws ClassNotFoundException {
157 SyntheticRepository repos = createRepos("testcode.jar");
158 JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
159 verifyComplexAnnotation(clazz);
163 public void testComplexAnnotationsReadWrite() throws ClassNotFoundException, IOException {
164 SyntheticRepository repos = createRepos("testcode.jar");
165 JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
166 verifyComplexAnnotation(clazz);
169 File tfile = createTestdataFile("ComplexAnnotatedClass.class");
172 SyntheticRepository repos2 = createRepos(".");
173 JavaClass clazz2 = repos.loadClass("ComplexAnnotatedClass");
174 verifyComplexAnnotation(clazz2);
176 assertTrue(tfile.delete());
180 private void verifyComplexAnnotation(JavaClass clazz) {
181 AnnotationGen[] anns = clazz.getAnnotations();
182 assertTrue("Should be one annotation but found "+anns.length,anns.length==1);
183 AnnotationGen ann = anns[0];
184 assertTrue("Should be called 'ComplexAnnotation' but was called "+ann.getTypeName(),
185 ann.getTypeName().equals("ComplexAnnotation"));
186 List l = ann.getValues();
187 assertTrue("Should be eight values for annotation 'ComplexAnnotation' but found "+l.size(),
189 List names = RuntimeVisibleAnnotationAttributeTest.getListOfAnnotationNames(ann);
190 assertTrue("Cant find expected element ",names.contains("ival"));
191 assertTrue("Cant find expected element ",names.contains("dval"));
192 assertTrue("Cant find expected element ",names.contains("zval"));
193 assertTrue("Cant find expected element ",names.contains("fval"));
194 assertTrue("Cant find expected element ",names.contains("jval"));
195 assertTrue("Cant find expected element ",names.contains("sval"));
196 assertTrue("Cant find expected element ",names.contains("bval"));
197 assertTrue("Cant find expected element ",names.contains("cval"));
199 checkValue(ann,"ival","4");
200 checkValue(ann,"jval","56");
201 checkValue(ann,"fval","3.0");
202 checkValue(ann,"dval","33.4");
203 checkValue(ann,"sval","99");
204 checkValue(ann,"bval","2");
205 checkValue(ann,"cval",new Character('5').toString());
206 checkValue(ann,"zval","false");
210 private void checkValue(AnnotationGen a,String name,String tostring) {
211 for (Iterator i = a.getValues().iterator(); i.hasNext();) {
212 ElementNameValuePairGen element = (ElementNameValuePairGen) i.next();
213 if (element.getNameString().equals(name)) {
214 if (!element.getValue().stringifyValue().equals(tostring)) {
215 fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
220 fail("Didnt find named element "+name);
224 // Test an annotation containing a 'Class' element
226 public void testAnnotationClassElement() throws ClassNotFoundException {
227 SyntheticRepository repos = createRepos("testcode.jar");
228 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
229 verifyClassAnnotation(clazz);
232 public void testAnnotationClassElementCopying() throws ClassNotFoundException {
233 SyntheticRepository repos = createRepos("testcode.jar");
234 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
235 AnnotationGen[] anns = clazz.getAnnotations();
236 ClassGen cg = new ClassGen(clazz);
237 // Checks we can copy class values in an annotation
238 new AnnotationGen(anns[0],cg.getConstantPool(),true);
239 new AnnotationGen(anns[0],cg.getConstantPool(),false);
242 public void testAnnotationClassElementReadWrite() throws ClassNotFoundException,IOException {
243 SyntheticRepository repos = createRepos("testcode.jar");
244 JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
245 verifyClassAnnotation(clazz);
248 File tfile = createTestdataFile("AnnotatedWithClassClass.class");
251 SyntheticRepository repos2 = createRepos(".");
252 JavaClass clazz2 = repos2.loadClass("AnnotatedWithClassClass");
253 verifyClassAnnotation(clazz2);
255 assertTrue(wipe("AnnotatedWithClassClass.class"));
258 private void verifyClassAnnotation(JavaClass clazz) {
259 AnnotationGen[] anns = clazz.getAnnotations();
260 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
261 AnnotationGen ann = anns[0];
262 assertTrue("should be called 'AnnotationClassElement' but was called "+ann.getTypeName(),
263 ann.getTypeName().equals("AnnotationClassElement"));
264 List l = ann.getValues();
265 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
266 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
267 assertTrue("Name of element should be 'clz' but was "+nvp.getNameString(),
268 nvp.getNameString().equals("clz"));
269 ClassElementValueGen ev = (ClassElementValueGen)nvp.getValue();
270 assertTrue("String value should be 'Ljava/lang/Integer;' but was '"+ev.getClassString()+"'",
271 ev.getClassString().equals("Ljava/lang/Integer;"));
276 // Test an annotation containing an enum element
278 public void testAnnotationEnumElement() throws ClassNotFoundException {
279 SyntheticRepository repos = createRepos("testcode.jar");
280 JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
281 verifyAnnotationEnumElement(clazz);
284 public void testAnnotationEnumElementReadWrite() throws ClassNotFoundException, IOException {
285 SyntheticRepository repos = createRepos("testcode.jar");
286 JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
287 verifyAnnotationEnumElement(clazz);
290 File tfile = createTestdataFile("AnnotatedWithEnumClass.class");
293 SyntheticRepository repos2 = createRepos(".");
294 JavaClass clazz2 = repos2.loadClass("AnnotatedWithEnumClass");
295 verifyAnnotationEnumElement(clazz2);
297 assertTrue(tfile.delete());
300 public void verifyAnnotationEnumElement(JavaClass clazz) {
301 AnnotationGen[] anns = clazz.getAnnotations();
302 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
303 AnnotationGen ann = anns[0];
304 assertTrue("should be called 'AnnotationEnumElement' but was called "+ann.getTypeName(),
305 ann.getTypeName().equals("AnnotationEnumElement"));
306 List l = ann.getValues();
307 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
308 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
309 assertTrue("Name of element should be 'enumval' but was "+nvp.getNameString(),
310 nvp.getNameString().equals("enumval"));
311 ElementValueGen ev = nvp.getValue();
312 assertTrue("Should be of type EnumElementValue but is "+ev,ev instanceof EnumElementValueGen);
313 EnumElementValueGen eev = (EnumElementValueGen)ev;
314 assertTrue("Should be an enum type value but is "+eev.getElementValueType(),eev.getElementValueType()==SimpleElementValueGen.ENUM_CONSTANT);
315 assertTrue("Enum type for annotation should be 'SimpleEnum' but is "+Utility.signatureToString(eev.getEnumTypeString()),Utility.signatureToString(eev.getEnumTypeString()).equals("SimpleEnum"));
316 assertTrue("String value should be 'Red' but was '"+eev.getEnumValueString()+"'",
317 eev.getEnumValueString().equals("Red"));
321 // Test an annotation with an array element
323 public void testAnnotationArraysOfAnnotations() throws ClassNotFoundException {
324 SyntheticRepository repos = createRepos("testcode.jar");
325 JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
326 AnnotationGen[] anns = clazz.getAnnotations();
327 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
328 checkCombinedAnnotation(anns[0]);
331 public void testAnnotationArraysOfAnnotationsReadWrite() throws ClassNotFoundException, IOException {
332 SyntheticRepository repos = createRepos("testcode.jar");
333 JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
334 AnnotationGen[] anns = clazz.getAnnotations();
335 assertTrue("should be one annotation but found "+anns.length,anns.length==1);
336 checkCombinedAnnotation(anns[0]);
339 File tfile = createTestdataFile("AnnotatedWithCombinedAnnotation.class");
342 SyntheticRepository repos2 = createRepos(".");
343 JavaClass clazz2 = repos2.loadClass("AnnotatedWithCombinedAnnotation");
344 AnnotationGen[] anns2 = clazz2.getAnnotations();
345 assertTrue("should be one annotation but found "+anns2.length,anns2.length==1);
346 checkCombinedAnnotation(anns2[0]);
348 assertTrue(tfile.delete());
352 private void checkCombinedAnnotation(AnnotationGen ann) {
353 assertTrue("should be called 'CombinedAnnotation' but was called "+ann.getTypeName(),
354 ann.getTypeName().equals("CombinedAnnotation"));
355 List l = ann.getValues();
356 assertTrue("Should be one value but there were "+l.size(),l.size()==1);
357 ElementNameValuePairGen nvp = (ElementNameValuePairGen)l.get(0);
358 assertTrue("Name of element should be 'value' but was "+nvp.getNameString(),
359 nvp.getNameString().equals("value"));
360 ElementValueGen ev = nvp.getValue();
361 assertTrue("Should be of type ArrayElementValue but is "+ev,ev instanceof ArrayElementValueGen);
362 ArrayElementValueGen aev = (ArrayElementValueGen)ev;
364 assertTrue("Array element value should be of size 1 but is "+aev.getElementValuesArraySize(),
365 aev.getElementValuesArraySize()==1);
366 ElementValueGen[] evs = aev.getElementValuesArray();
367 assertTrue("Entry in the array should be AnnotationElementValue but is "+evs[0],
368 evs[0] instanceof AnnotationElementValueGen);
369 AnnotationElementValueGen inner_ev = (AnnotationElementValueGen)evs[0];
370 AnnotationGen a = inner_ev.getAnnotation();
371 assertTrue("Should be SimpleAnnotation but is "+a.getTypeName(),a.getTypeName().equals("SimpleAnnotation"));
372 List envps = a.getValues();
373 assertTrue("Should be one name value pair but found "+envps.size(),envps.size()==1);
374 ElementNameValuePairGen envp = (ElementNameValuePairGen) envps.get(0);
375 assertTrue("Name should be 'id' but it is "+envp.getNameString(),envp.getNameString().equals("id"));
376 assertTrue("Value of 'id' should be 4 but it is "+envp.getValue().stringifyValue(),
377 envp.getValue().stringifyValue().equals("4"));
381 protected void tearDown() throws Exception {
385 public static List getListOfAnnotationNames(AnnotationGen a) {
386 List l = a.getValues();
387 List names = new ArrayList();
388 for (Iterator i = l.iterator(); i.hasNext();) {
389 ElementNameValuePairGen element = (ElementNameValuePairGen) i.next();
390 names.add(element.getNameString());