You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RuntimeVisibleAnnotationAttributeTest.java 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. /* *******************************************************************
  2. * Copyright (c) 2004 IBM
  3. * All rights reserved.
  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
  8. *
  9. * Contributors:
  10. * Andy Clement - initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.apache.bcel.classfile.tests;
  13. import java.io.File;
  14. import java.io.IOException;
  15. import java.util.ArrayList;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import org.aspectj.apache.bcel.classfile.Attribute;
  19. import org.aspectj.apache.bcel.classfile.ConstantPool;
  20. import org.aspectj.apache.bcel.classfile.JavaClass;
  21. import org.aspectj.apache.bcel.classfile.Utility;
  22. import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValue;
  23. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  24. import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
  25. import org.aspectj.apache.bcel.classfile.annotation.ClassElementValue;
  26. import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
  27. import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
  28. import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
  29. import org.aspectj.apache.bcel.classfile.annotation.RuntimeVisAnnos;
  30. import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
  31. import org.aspectj.apache.bcel.generic.ClassGen;
  32. import org.aspectj.apache.bcel.util.SyntheticRepository;
  33. public class RuntimeVisibleAnnotationAttributeTest extends BcelTestCase {
  34. protected void setUp() throws Exception {
  35. super.setUp();
  36. }
  37. public void testSeeAnnotationsAsAttribute() throws ClassNotFoundException {
  38. SyntheticRepository repos = createRepos("testcode.jar");
  39. JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
  40. ConstantPool pool = clazz.getConstantPool();
  41. Attribute[] rvaAttr = findAttribute("RuntimeVisibleAnnotations",clazz);
  42. assertTrue("Expected a RuntimeVisibleAnnotations attribute but found none",
  43. rvaAttr.length==1);
  44. }
  45. public void testAnnotationsAttributeContainsRightData() 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. RuntimeVisAnnos rva = (RuntimeVisAnnos) rvaAttr[0];
  51. List<AnnotationGen> anns = rva.getAnnotations();
  52. assertTrue("Should be one annotation but found "+anns.size(),
  53. anns.size()==1);
  54. AnnotationGen ann = anns.get(0);
  55. assertTrue("Should be called 'SimpleAnnotation' but was called "+ann.getTypeName(),
  56. ann.getTypeName().equals("SimpleAnnotation"));
  57. List<NameValuePair> l = ann.getValues();
  58. assertTrue("Should be one value for annotation 'SimpleAnnotation' but found "+l.size(),
  59. l.size()==1);
  60. NameValuePair envp = l.get(0);
  61. assertTrue("Name of element in SimpleAnnotation should be 'id' but it is "+envp.getNameString(),
  62. envp.getNameString().equals("id"));
  63. SimpleElementValue evalue = (SimpleElementValue)envp.getValue();
  64. assertTrue("'id' should be of type int, but it is "+evalue.getElementValueType(),evalue.getElementValueType()==SimpleElementValue.PRIMITIVE_INT);
  65. assertTrue("'id' should have value 4 but it is "+evalue.getValueInt(),
  66. evalue.getValueInt()==4);
  67. }
  68. public void testAccessingAnnotationsOnClazz() throws ClassNotFoundException {
  69. SyntheticRepository repos = createRepos("testcode.jar");
  70. JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
  71. ConstantPool pool = clazz.getConstantPool();
  72. AnnotationGen[] anns = clazz.getAnnotations();
  73. assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
  74. anns.length==1);
  75. }
  76. public void testReadingWritingAnnotations() throws ClassNotFoundException, IOException {
  77. SyntheticRepository repos = createRepos("testcode.jar");
  78. JavaClass clazz = repos.loadClass("SimpleAnnotatedClass");
  79. ConstantPool pool = clazz.getConstantPool();
  80. AnnotationGen[] anns = clazz.getAnnotations();
  81. assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns.length,
  82. anns.length==1);
  83. // Write it out
  84. File tfile = createTestdataFile("SimpleAnnotatedClass.class");
  85. clazz.dump(tfile);
  86. SyntheticRepository repos2 = createRepos(".");
  87. JavaClass clazz2 = repos.loadClass("SimpleAnnotatedClass");
  88. ConstantPool pool2 = clazz2.getConstantPool();
  89. AnnotationGen[] anns2 = clazz2.getAnnotations();
  90. assertTrue("Expected one annotation on SimpleAnnotatedClass class but got "+anns2.length,
  91. anns2.length==1);
  92. assertTrue(tfile.delete());
  93. }
  94. ////
  95. // Test for annotations containing string elements
  96. public void testAnnotationStringElement() throws ClassNotFoundException {
  97. SyntheticRepository repos = createRepos("testcode.jar");
  98. JavaClass clazz = repos.loadClass("AnnotatedClass");
  99. verifyAnnotationStringElement(clazz);
  100. }
  101. public void testAnnotationStringElementReadWrite() throws ClassNotFoundException, IOException {
  102. SyntheticRepository repos = createRepos("testcode.jar");
  103. JavaClass clazz = repos.loadClass("AnnotatedClass");
  104. verifyAnnotationStringElement(clazz);
  105. // Write it out
  106. File tfile = createTestdataFile("AnnotatedClass.class");
  107. clazz.dump(tfile);
  108. SyntheticRepository repos2 = createRepos(".");
  109. JavaClass clazz2 = repos2.loadClass("AnnotatedClass");
  110. verifyAnnotationStringElement(clazz2);
  111. assertTrue(tfile.delete());
  112. }
  113. private void verifyAnnotationStringElement(JavaClass clazz) {
  114. AnnotationGen[] anns = clazz.getAnnotations();
  115. assertTrue("should be one annotation but found "+anns.length,anns.length==1);
  116. AnnotationGen ann = anns[0];
  117. assertTrue("should be called 'AnnotationStringElement' but was called "+ann.getTypeName(),
  118. ann.getTypeName().equals("AnnotationStringElement"));
  119. List<NameValuePair> l = ann.getValues();
  120. assertTrue("Should be one value but there were "+l.size(),l.size()==1);
  121. NameValuePair nvp = l.get(0);
  122. assertTrue("Name of element should be 'stringval' but was "+nvp.getNameString(),
  123. nvp.getNameString().equals("stringval"));
  124. SimpleElementValue ev = (SimpleElementValue)nvp.getValue();
  125. assertTrue("String value should be 'hello' but was '"+ev.getValueString()+"'",
  126. ev.getValueString().equals("hello"));
  127. }
  128. ////
  129. // Test for complex annotation that includes all primitives
  130. public void testComplexAnnotation() throws ClassNotFoundException {
  131. SyntheticRepository repos = createRepos("testcode.jar");
  132. JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
  133. verifyComplexAnnotation(clazz);
  134. }
  135. public void testComplexAnnotationsReadWrite() throws ClassNotFoundException, IOException {
  136. SyntheticRepository repos = createRepos("testcode.jar");
  137. JavaClass clazz = repos.loadClass("ComplexAnnotatedClass");
  138. verifyComplexAnnotation(clazz);
  139. // Write it out
  140. File tfile = createTestdataFile("ComplexAnnotatedClass.class");
  141. clazz.dump(tfile);
  142. SyntheticRepository repos2 = createRepos(".");
  143. JavaClass clazz2 = repos.loadClass("ComplexAnnotatedClass");
  144. verifyComplexAnnotation(clazz2);
  145. assertTrue(tfile.delete());
  146. }
  147. private void verifyComplexAnnotation(JavaClass clazz) {
  148. AnnotationGen[] anns = clazz.getAnnotations();
  149. assertTrue("Should be one annotation but found "+anns.length,anns.length==1);
  150. AnnotationGen ann = anns[0];
  151. assertTrue("Should be called 'ComplexAnnotation' but was called "+ann.getTypeName(),
  152. ann.getTypeName().equals("ComplexAnnotation"));
  153. List<NameValuePair> l = ann.getValues();
  154. assertTrue("Should be eight values for annotation 'ComplexAnnotation' but found "+l.size(),
  155. l.size()==8);
  156. List<String> names = RuntimeVisibleAnnotationAttributeTest.getListOfAnnotationNames(ann);
  157. assertTrue("Cant find expected element ",names.contains("ival"));
  158. assertTrue("Cant find expected element ",names.contains("dval"));
  159. assertTrue("Cant find expected element ",names.contains("zval"));
  160. assertTrue("Cant find expected element ",names.contains("fval"));
  161. assertTrue("Cant find expected element ",names.contains("jval"));
  162. assertTrue("Cant find expected element ",names.contains("sval"));
  163. assertTrue("Cant find expected element ",names.contains("bval"));
  164. assertTrue("Cant find expected element ",names.contains("cval"));
  165. checkValue(ann,"ival","4");
  166. checkValue(ann,"jval","56");
  167. checkValue(ann,"fval","3.0");
  168. checkValue(ann,"dval","33.4");
  169. checkValue(ann,"sval","99");
  170. checkValue(ann,"bval","2");
  171. checkValue(ann,"cval",new Character('5').toString());
  172. checkValue(ann,"zval","false");
  173. }
  174. private void checkValue(AnnotationGen a,String name,String tostring) {
  175. for (Iterator<NameValuePair> i = a.getValues().iterator(); i.hasNext();) {
  176. NameValuePair element = i.next();
  177. if (element.getNameString().equals(name)) {
  178. if (!element.getValue().stringifyValue().equals(tostring)) {
  179. fail("Expected element "+name+" to have value "+tostring+" but it had value "+element.getValue().stringifyValue());
  180. }
  181. return;
  182. }
  183. }
  184. fail("Didnt find named element "+name);
  185. }
  186. ////
  187. // Test an annotation containing a 'Class' element
  188. public void testAnnotationClassElement() throws ClassNotFoundException {
  189. SyntheticRepository repos = createRepos("testcode.jar");
  190. JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
  191. verifyClassAnnotation(clazz);
  192. }
  193. public void testAnnotationClassElementCopying() throws ClassNotFoundException {
  194. SyntheticRepository repos = createRepos("testcode.jar");
  195. JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
  196. AnnotationGen[] anns = clazz.getAnnotations();
  197. ClassGen cg = new ClassGen(clazz);
  198. // Checks we can copy class values in an annotation
  199. new AnnotationGen(anns[0],cg.getConstantPool(),true);
  200. new AnnotationGen(anns[0],cg.getConstantPool(),false);
  201. }
  202. public void testAnnotationClassElementReadWrite() throws ClassNotFoundException,IOException {
  203. SyntheticRepository repos = createRepos("testcode.jar");
  204. JavaClass clazz = repos.loadClass("AnnotatedWithClassClass");
  205. verifyClassAnnotation(clazz);
  206. // Write it out
  207. File tfile = createTestdataFile("AnnotatedWithClassClass.class");
  208. clazz.dump(tfile);
  209. SyntheticRepository repos2 = createRepos(".");
  210. JavaClass clazz2 = repos2.loadClass("AnnotatedWithClassClass");
  211. verifyClassAnnotation(clazz2);
  212. assertTrue(wipe("AnnotatedWithClassClass.class"));
  213. }
  214. private void verifyClassAnnotation(JavaClass clazz) {
  215. AnnotationGen[] anns = clazz.getAnnotations();
  216. assertTrue("should be one annotation but found "+anns.length,anns.length==1);
  217. AnnotationGen ann = anns[0];
  218. assertTrue("should be called 'AnnotationClassElement' but was called "+ann.getTypeName(),
  219. ann.getTypeName().equals("AnnotationClassElement"));
  220. List<NameValuePair> l = ann.getValues();
  221. assertTrue("Should be one value but there were "+l.size(),l.size()==1);
  222. NameValuePair nvp = l.get(0);
  223. assertTrue("Name of element should be 'clz' but was "+nvp.getNameString(),
  224. nvp.getNameString().equals("clz"));
  225. ClassElementValue ev = (ClassElementValue)nvp.getValue();
  226. assertTrue("String value should be 'Ljava/lang/Integer;' but was '"+ev.getClassString()+"'",
  227. ev.getClassString().equals("Ljava/lang/Integer;"));
  228. }
  229. ////
  230. // Test an annotation containing an enum element
  231. public void testAnnotationEnumElement() throws ClassNotFoundException {
  232. SyntheticRepository repos = createRepos("testcode.jar");
  233. JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
  234. verifyAnnotationEnumElement(clazz);
  235. }
  236. public void testAnnotationEnumElementReadWrite() throws ClassNotFoundException, IOException {
  237. SyntheticRepository repos = createRepos("testcode.jar");
  238. JavaClass clazz = repos.loadClass("AnnotatedWithEnumClass");
  239. verifyAnnotationEnumElement(clazz);
  240. // Write it out
  241. File tfile = createTestdataFile("AnnotatedWithEnumClass.class");
  242. clazz.dump(tfile);
  243. SyntheticRepository repos2 = createRepos(".");
  244. JavaClass clazz2 = repos2.loadClass("AnnotatedWithEnumClass");
  245. verifyAnnotationEnumElement(clazz2);
  246. assertTrue(tfile.delete());
  247. }
  248. public void verifyAnnotationEnumElement(JavaClass clazz) {
  249. AnnotationGen[] anns = clazz.getAnnotations();
  250. assertTrue("should be one annotation but found "+anns.length,anns.length==1);
  251. AnnotationGen ann = anns[0];
  252. assertTrue("should be called 'AnnotationEnumElement' but was called "+ann.getTypeName(),
  253. ann.getTypeName().equals("AnnotationEnumElement"));
  254. List<NameValuePair> l = ann.getValues();
  255. assertTrue("Should be one value but there were "+l.size(),l.size()==1);
  256. NameValuePair nvp = l.get(0);
  257. assertTrue("Name of element should be 'enumval' but was "+nvp.getNameString(),
  258. nvp.getNameString().equals("enumval"));
  259. ElementValue ev = nvp.getValue();
  260. assertTrue("Should be of type EnumElementValue but is "+ev,ev instanceof EnumElementValue);
  261. EnumElementValue eev = (EnumElementValue)ev;
  262. assertTrue("Should be an enum type value but is "+eev.getElementValueType(),eev.getElementValueType()==SimpleElementValue.ENUM_CONSTANT);
  263. assertTrue("Enum type for annotation should be 'SimpleEnum' but is "+Utility.signatureToString(eev.getEnumTypeString()),Utility.signatureToString(eev.getEnumTypeString()).equals("SimpleEnum"));
  264. assertTrue("String value should be 'Red' but was '"+eev.getEnumValueString()+"'",
  265. eev.getEnumValueString().equals("Red"));
  266. }
  267. ////
  268. // Test an annotation with an array element
  269. public void testAnnotationArraysOfAnnotations() throws ClassNotFoundException {
  270. SyntheticRepository repos = createRepos("testcode.jar");
  271. JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
  272. AnnotationGen[] anns = clazz.getAnnotations();
  273. assertTrue("should be one annotation but found "+anns.length,anns.length==1);
  274. checkCombinedAnnotation(anns[0]);
  275. }
  276. public void testAnnotationArraysOfAnnotationsReadWrite() throws ClassNotFoundException, IOException {
  277. SyntheticRepository repos = createRepos("testcode.jar");
  278. JavaClass clazz = repos.loadClass("AnnotatedWithCombinedAnnotation");
  279. AnnotationGen[] anns = clazz.getAnnotations();
  280. assertTrue("should be one annotation but found "+anns.length,anns.length==1);
  281. checkCombinedAnnotation(anns[0]);
  282. // Write it out
  283. File tfile = createTestdataFile("AnnotatedWithCombinedAnnotation.class");
  284. clazz.dump(tfile);
  285. SyntheticRepository repos2 = createRepos(".");
  286. JavaClass clazz2 = repos2.loadClass("AnnotatedWithCombinedAnnotation");
  287. AnnotationGen[] anns2 = clazz2.getAnnotations();
  288. assertTrue("should be one annotation but found "+anns2.length,anns2.length==1);
  289. checkCombinedAnnotation(anns2[0]);
  290. assertTrue(tfile.delete());
  291. }
  292. private void checkCombinedAnnotation(AnnotationGen ann) {
  293. assertTrue("should be called 'CombinedAnnotation' but was called "+ann.getTypeName(),
  294. ann.getTypeName().equals("CombinedAnnotation"));
  295. List<NameValuePair> l = ann.getValues();
  296. assertTrue("Should be one value but there were "+l.size(),l.size()==1);
  297. NameValuePair nvp = l.get(0);
  298. assertTrue("Name of element should be 'value' but was "+nvp.getNameString(),
  299. nvp.getNameString().equals("value"));
  300. ElementValue ev = nvp.getValue();
  301. assertTrue("Should be of type ArrayElementValue but is "+ev,ev instanceof ArrayElementValue);
  302. ArrayElementValue aev = (ArrayElementValue)ev;
  303. assertTrue("Array element value should be of size 1 but is "+aev.getElementValuesArraySize(),
  304. aev.getElementValuesArraySize()==1);
  305. ElementValue[] evs = aev.getElementValuesArray();
  306. assertTrue("Entry in the array should be AnnotationElementValue but is "+evs[0],
  307. evs[0] instanceof AnnotationElementValue);
  308. AnnotationElementValue inner_ev = (AnnotationElementValue)evs[0];
  309. AnnotationGen a = inner_ev.getAnnotation();
  310. assertTrue("Should be SimpleAnnotation but is "+a.getTypeName(),a.getTypeName().equals("SimpleAnnotation"));
  311. List<NameValuePair> envps = a.getValues();
  312. assertTrue("Should be one name value pair but found "+envps.size(),envps.size()==1);
  313. NameValuePair envp = envps.get(0);
  314. assertTrue("Name should be 'id' but it is "+envp.getNameString(),envp.getNameString().equals("id"));
  315. assertTrue("Value of 'id' should be 4 but it is "+envp.getValue().stringifyValue(),
  316. envp.getValue().stringifyValue().equals("4"));
  317. }
  318. protected void tearDown() throws Exception {
  319. super.tearDown();
  320. }
  321. public static List<String> getListOfAnnotationNames(AnnotationGen a) {
  322. List<NameValuePair> l = a.getValues();
  323. List<String> names = new ArrayList<String>();
  324. for (Iterator<NameValuePair> i = l.iterator(); i.hasNext();) {
  325. NameValuePair element = i.next();
  326. names.add(element.getNameString());
  327. }
  328. return names;
  329. }
  330. }