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.

ParameterAnnotationsTest.java 25KB

14 years ago
16 years ago
14 years ago
14 years ago
16 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. /*******************************************************************************
  2. * Copyright (c) 2004 IBM All rights reserved. This program and the accompanying
  3. * materials are made available under the terms of the Eclipse Public License
  4. * v1.0 which accompanies this distribution and is available at
  5. * http://www.eclipse.org/legal/epl-v10.html
  6. *
  7. * Contributors: Andy Clement - initial implementation
  8. ******************************************************************************/
  9. package org.aspectj.apache.bcel.classfile.tests;
  10. import java.io.File;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import org.aspectj.apache.bcel.Constants;
  14. import org.aspectj.apache.bcel.classfile.Attribute;
  15. import org.aspectj.apache.bcel.classfile.ConstantPool;
  16. import org.aspectj.apache.bcel.classfile.JavaClass;
  17. import org.aspectj.apache.bcel.classfile.Method;
  18. import org.aspectj.apache.bcel.classfile.annotation.AnnotationElementValue;
  19. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  20. import org.aspectj.apache.bcel.classfile.annotation.ArrayElementValue;
  21. import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
  22. import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
  23. import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
  24. import org.aspectj.apache.bcel.generic.ArrayType;
  25. import org.aspectj.apache.bcel.generic.ClassGen;
  26. import org.aspectj.apache.bcel.generic.InstructionBranch;
  27. import org.aspectj.apache.bcel.generic.InstructionConstants;
  28. import org.aspectj.apache.bcel.generic.InstructionFactory;
  29. import org.aspectj.apache.bcel.generic.InstructionHandle;
  30. import org.aspectj.apache.bcel.generic.InstructionLV;
  31. import org.aspectj.apache.bcel.generic.InstructionList;
  32. import org.aspectj.apache.bcel.generic.LocalVariableGen;
  33. import org.aspectj.apache.bcel.generic.MethodGen;
  34. import org.aspectj.apache.bcel.generic.ObjectType;
  35. import org.aspectj.apache.bcel.generic.Type;
  36. import org.aspectj.apache.bcel.util.SyntheticRepository;
  37. /**
  38. * The program that some of the tests generate looks like this:
  39. public class HelloWorld {
  40. public static void main(String[] argv) {
  41. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  42. String name = null;
  43. try {
  44. name = "Andy";
  45. } catch(IOException e) { return; }
  46. System.out.println("Hello, " + name);
  47. }
  48. }
  49. *
  50. */
  51. public class ParameterAnnotationsTest extends BcelTestCase {
  52. protected void setUp() throws Exception {
  53. super.setUp();
  54. }
  55. /**
  56. * Programmatically construct a class and add an annotation to the main method parameter 'argv'
  57. */
  58. public void testParameterAnnotations_builtOK() {
  59. ClassGen clg = createClassGen("HelloWorld");
  60. ConstantPool cpg = clg.getConstantPool();
  61. InstructionList il = new InstructionList();
  62. buildClassContentsWithAnnotatedMethods(clg,cpg,il,true);
  63. int i = clg.getMethods().length;
  64. assertTrue("Class should have 2 methods but has "+i,i==2);
  65. Method mainMethod = clg.getMethods()[0];
  66. AnnotationGen[] annos = mainMethod.getAnnotationsOnParameter(0);
  67. assertTrue("Should be two annotation on the 'argv' parameter to main() but there are "+annos.length,annos.length==2);
  68. assertTrue("This annotation should contain the string 'fruit=Apples' but it is "+annos[0].toString(),
  69. annos[0].toString().indexOf("fruit=Apples")!=-1);
  70. assertTrue("This annotation should contain the string 'fruit=Oranges' but it is "+annos[1].toString(),
  71. annos[1].toString().indexOf("fruit=Oranges")!=-1);
  72. }
  73. /**
  74. * Check we can save and load a constructed class that contains parameter annotations
  75. */
  76. public void testParameterAnnotations_savedAndLoadedOK() throws ClassNotFoundException {
  77. ClassGen clg = createClassGen("HelloWorld");
  78. ConstantPool cpg = clg.getConstantPool();
  79. InstructionList il = new InstructionList();
  80. buildClassContentsWithAnnotatedMethods(clg,cpg,il,true);
  81. dumpClass(clg,"temp5","HelloWorld.class");
  82. JavaClass jc = getClassFrom("temp5","HelloWorld");
  83. clg = new ClassGen(jc);
  84. int i = clg.getMethods().length;
  85. assertTrue("Class should have 2 methods but has "+i,i==2);
  86. Method mainMethod = clg.getMethods()[0];
  87. AnnotationGen[] annos = mainMethod.getAnnotationsOnParameter(0);
  88. assertTrue("Should be two annotation on the 'argv' parameter to main() but there are "+annos.length,annos.length==2);
  89. assertTrue("This annotation should contain the string 'fruit=Apples' but it is "+annos[0].toString(),
  90. annos[0].toString().indexOf("fruit=Apples")!=-1);
  91. assertTrue("This annotation should contain the string 'fruit=Oranges' but it is "+annos[1].toString(),
  92. annos[1].toString().indexOf("fruit=Oranges")!=-1);
  93. assertTrue(wipe("temp5","HelloWorld.class"));
  94. }
  95. /*
  96. * Load an existing class, add new parameter annotations, save and then reload it
  97. */
  98. public void testParameterAnnotations_loadedThenModifiedThenSavedAndLoadedOK() throws ClassNotFoundException {
  99. JavaClass jc = getClassFrom("testcode.jar","AnnotatedParameters");
  100. ClassGen clg = new ClassGen(jc);
  101. ConstantPool cpg = clg.getConstantPool();
  102. //
  103. // Foo method looks like this:
  104. // public void foo(@SimpleAnnotation(id=2) int arg1,
  105. // @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
  106. Method m = findMethod(clg,"foo");
  107. assertTrue("Should be able to find method foo but couldn't",m!=null);
  108. /////////////////////// 1. Check the right number of annotations are there
  109. int i = m.getAnnotationsOnParameter(1).length;
  110. assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
  111. /////////////////////// 2. Let's add a new parameter annotation, a visible one, to the first parameter.
  112. // Build a modifiable version of the foo method
  113. MethodGen mg = new MethodGen(m,clg.getClassName(),cpg);
  114. // Check the annotations survived that transform
  115. i = mg.getAnnotationsOnParameter(1).size();
  116. assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
  117. // That worked, so let's add a new parameter annotation
  118. mg.addParameterAnnotation(0,createFruitAnnotation(cpg,"Banana",true));
  119. // Foo method should now look like this:
  120. // public void foo(@SimpleAnnotation(id=2) @SimpleStringAnnotation(fruit=Banana) int arg1,
  121. // @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
  122. i = mg.getAnnotationsOnParameter(0).size();
  123. assertTrue("Should now be 2 parameter annotations but found "+i,i==2);
  124. i = mg.getAnnotationsOnParameter(0).get(1).toString().indexOf("fruit=Banana");
  125. assertTrue("Expected 'fruit=Banana' in the 2nd annotation on the first argument but got "+
  126. mg.getAnnotationsOnParameter(0).get(1).toString(),i!=-1);
  127. // delete the old method and add the new one
  128. clg.removeMethod(m);
  129. clg.addMethod(mg.getMethod());
  130. /////////////////////// 3. Dump it to disk
  131. dumpClass(clg,"temp2","AnnotatedParameters.class");
  132. /////////////////////// 4. Load it back in and verify the annotations persisted
  133. JavaClass jc2 = getClassFrom("temp2","AnnotatedParameters");
  134. m = jc2.getMethods()[2];
  135. AnnotationGen[] p1annotations = m.getAnnotationsOnParameter(0);
  136. AnnotationGen[] p2annotations = m.getAnnotationsOnParameter(1);
  137. assertTrue("Expected two annotations on the first parameter but found "+p1annotations.length,p1annotations.length==2);
  138. assertTrue("Expected two annotations on the second parameter but found "+p2annotations.length,p2annotations.length==2);
  139. String expectedString = "[@SimpleAnnotation(id=2),@SimpleStringAnnotation(fruit=Banana)]";
  140. assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p1annotations)+"'",
  141. dumpAnnotations(p1annotations).equals(expectedString));
  142. expectedString = "[@SimpleAnnotation(id=3),@AnnotationEnumElement(enumval=LSimpleEnum;Red)]";
  143. assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p2annotations)+"'",
  144. dumpAnnotations(p2annotations).equals(expectedString));
  145. assertTrue(wipe("temp2","AnnotatedParameters.class"));
  146. }
  147. /**
  148. * same as above test but attaching invisible runtime parameter annotations
  149. */
  150. public void testParameterAnnotations_loadedThenModifiedWithInvisibleAnnotationThenSavedAndLoadedOK() throws ClassNotFoundException {
  151. JavaClass jc = getClassFrom("testcode.jar","AnnotatedParameters");
  152. ClassGen clg = new ClassGen(jc);
  153. ConstantPool cpg = clg.getConstantPool();
  154. //
  155. // Foo method looks like this:
  156. // public void foo(@SimpleAnnotation(id=2) int arg1,
  157. // @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
  158. Method m = findMethod(clg,"foo");
  159. assertTrue("Should be able to find method foo but couldn't",m!=null);
  160. /////////////////////// 1. Check the right number of annotations are there
  161. int i = m.getAnnotationsOnParameter(1).length;
  162. assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
  163. /////////////////////// 2. Let's add a new parameter annotation, a visible one, to the first parameter.
  164. // Build a modifiable version of the foo method
  165. MethodGen mg = new MethodGen(m,clg.getClassName(),cpg);
  166. // Check the annotations survived that transform
  167. i = mg.getAnnotationsOnParameter(1).size();
  168. assertTrue("Should be two annotations on the second parameter but found: "+i,i==2);
  169. // That worked, so let's add a new parameter annotation
  170. mg.addParameterAnnotation(0,createFruitAnnotation(cpg,"Banana",false));
  171. // Foo method should now look like this:
  172. // public void foo(@SimpleAnnotation(id=2) @SimpleStringAnnotation(fruit=Banana) int arg1,
  173. // @SimpleAnnotation(id=3) @AnnotationEnumElement(enumval=SimpleEnum.Red) String arg2)
  174. i = mg.getAnnotationsOnParameter(0).size();
  175. assertTrue("Should now be 2 parameter annotations but found "+i,i==2);
  176. i = mg.getAnnotationsOnParameter(0).get(1).toString().indexOf("fruit=Banana");
  177. assertTrue("Expected 'fruit=Banana' in the 2nd annotation on the first argument but got "+
  178. mg.getAnnotationsOnParameter(0).get(1).toString(),i!=-1);
  179. assertTrue("New annotation should be runtime invisible?",!((AnnotationGen)mg.getAnnotationsOnParameter(0).get(1)).isRuntimeVisible());
  180. // delete the old method and add the new one
  181. clg.removeMethod(m);
  182. clg.addMethod(mg.getMethod());
  183. /////////////////////// 3. Dump it to disk
  184. dumpClass(clg,"temp3","AnnotatedParameters.class");
  185. /////////////////////// 4. Load it back in and verify the annotations persisted
  186. JavaClass jc2 = getClassFrom("temp3","AnnotatedParameters");
  187. m = jc2.getMethods()[2];
  188. AnnotationGen[] p1annotations = m.getAnnotationsOnParameter(0);
  189. AnnotationGen[] p2annotations = m.getAnnotationsOnParameter(1);
  190. assertTrue("Expected two annotations on the first parameter but found "+p1annotations.length,p1annotations.length==2);
  191. assertTrue("Expected two annotations on the second parameter but found "+p2annotations.length,p2annotations.length==2);
  192. String expectedString = "[@SimpleAnnotation(id=2),@SimpleStringAnnotation(fruit=Banana)]";
  193. assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p1annotations)+"'",
  194. dumpAnnotations(p1annotations).equals(expectedString));
  195. expectedString = "[@SimpleAnnotation(id=3),@AnnotationEnumElement(enumval=LSimpleEnum;Red)]";
  196. assertTrue("Expected formatted short string of '"+expectedString+"' but it was '"+dumpAnnotations(p2annotations)+"'",
  197. dumpAnnotations(p2annotations).equals(expectedString));
  198. assertTrue("Second annotation on first parameter should be runtime invisible?",
  199. !p1annotations[1].isRuntimeVisible());
  200. assertTrue(wipe("temp3","AnnotatedParameters.class"));
  201. // 5. Verify that when annotations for parameters are unpacked from attributes, the
  202. // attributes vanish !
  203. clg = new ClassGen(jc2);
  204. mg = new MethodGen(m,clg.getClassName(),clg.getConstantPool());
  205. List<Attribute> as = mg.getAttributes();
  206. assertTrue("Should be 2 (RIPA and RVPA) but there are "+mg.getAttributes().size(),mg.getAttributes().size()==2);
  207. List<AnnotationGen> l = mg.getAnnotationsOnParameter(0);
  208. assertTrue("Should be 2 annotations on first parameter but there is only "+l.size()+":"+l.toString(),
  209. l.size()==2);
  210. assertTrue("Should be 0 but there are "+mg.getAttributes().size(),mg.getAttributes().size()==0);
  211. }
  212. private Method findMethod(ClassGen c,String mname) {
  213. Method[] ms = c.getMethods();
  214. for (int i = 0; i < ms.length; i++) {
  215. if (ms[i].getName().equals(mname)) return ms[i];
  216. }
  217. return null;
  218. }
  219. private void dumpClass(ClassGen cg, String fname) {
  220. try {
  221. File f = createTestdataFile(fname);
  222. cg.getJavaClass().dump(f);
  223. } catch (java.io.IOException e) {
  224. System.err.println(e);
  225. }
  226. }
  227. private void dumpClass(ClassGen cg, String dir, String fname) {
  228. dumpClass(cg,dir+File.separator+fname);
  229. }
  230. private void buildClassContentsWithAnnotatedMethods(ClassGen cg, ConstantPool cp, InstructionList il,boolean addParameterAnnotations) {
  231. // Create method 'public static void main(String[]argv)'
  232. MethodGen mg = createMethodGen("main",il,cp);
  233. InstructionFactory factory = new InstructionFactory(cg);
  234. mg.addAnnotation(createSimpleVisibleAnnotation(mg.getConstantPool()));
  235. // We now define some often used types:
  236. ObjectType i_stream = new ObjectType("java.io.InputStream");
  237. ObjectType p_stream = new ObjectType("java.io.PrintStream");
  238. // Create variables in and name : We call the constructors, i.e.,
  239. // execute BufferedReader(InputStreamReader(System.in)) . The reference
  240. // to the BufferedReader object stays on top of the stack and is stored
  241. // in the newly allocated in variable.
  242. il.append(factory.createNew("java.io.BufferedReader"));
  243. il.append(InstructionConstants.DUP); // Use predefined constant
  244. il.append(factory.createNew("java.io.InputStreamReader"));
  245. il.append(InstructionConstants.DUP);
  246. il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
  247. il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
  248. Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
  249. il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
  250. Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
  251. Constants.INVOKESPECIAL));
  252. LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
  253. "java.io.BufferedReader"), null, null);
  254. int in = lg.getIndex();
  255. lg.setStart(il.append(InstructionFactory.createASTORE(in))); // "in" valid from here
  256. // Create local variable name and initialize it to null
  257. lg = mg.addLocalVariable("name", Type.STRING, null, null);
  258. int name = lg.getIndex();
  259. il.append(InstructionConstants.ACONST_NULL);
  260. lg.setStart(il.append(InstructionFactory.createASTORE(name))); // "name" valid from here
  261. // Create try-catch block: We remember the start of the block, read a
  262. // line from the standard input and store it into the variable name .
  263. // InstructionHandle try_start = il.append(factory.createFieldAccess(
  264. // "java.lang.System", "out", p_stream, Constants.GETSTATIC));
  265. // il.append(new PUSH(cp, "Please enter your name> "));
  266. // il.append(factory.createInvoke("java.io.PrintStream", "print",
  267. // Type.VOID, new Type[] { Type.STRING },
  268. // Constants.INVOKEVIRTUAL));
  269. // il.append(new ALOAD(in));
  270. // il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
  271. // Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
  272. InstructionHandle try_start = il.append(InstructionFactory.PUSH(cp,"Andy"));
  273. il.append(InstructionFactory.createASTORE(name));
  274. // Upon normal execution we jump behind exception handler, the target
  275. // address is not known yet.
  276. InstructionBranch g = new InstructionBranch(Constants.GOTO);
  277. InstructionHandle try_end = il.append(g);
  278. // We add the exception handler which simply returns from the method.
  279. LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
  280. int var_ex_slot = var_ex.getIndex();
  281. InstructionHandle handler = il.append(InstructionFactory.createASTORE(var_ex_slot));
  282. var_ex.setStart(handler);
  283. var_ex.setEnd(il.append(InstructionConstants.RETURN));
  284. mg.addExceptionHandler(try_start, try_end, handler,
  285. new ObjectType("java.io.IOException"));
  286. // "Normal" code continues, now we can set the branch target of the GOTO
  287. // .
  288. InstructionHandle ih = il.append(factory.createFieldAccess(
  289. "java.lang.System", "out", p_stream, Constants.GETSTATIC));
  290. g.setTarget(ih);
  291. // Printing "Hello": String concatenation compiles to StringBuffer
  292. // operations.
  293. il.append(factory.createNew(Type.STRINGBUFFER));
  294. il.append(InstructionConstants.DUP);
  295. il.append(InstructionFactory.PUSH(cp, "Hello, "));
  296. il
  297. .append(factory.createInvoke("java.lang.StringBuffer",
  298. "<init>", Type.VOID, new Type[] { Type.STRING },
  299. Constants.INVOKESPECIAL));
  300. il.append(new InstructionLV(Constants.ALOAD,name));
  301. il.append(factory.createInvoke("java.lang.StringBuffer", "append",
  302. Type.STRINGBUFFER, new Type[] { Type.STRING },
  303. Constants.INVOKEVIRTUAL));
  304. il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
  305. Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
  306. il.append(factory.createInvoke("java.io.PrintStream", "println",
  307. Type.VOID, new Type[] { Type.STRING },
  308. Constants.INVOKEVIRTUAL));
  309. il.append(InstructionConstants.RETURN);
  310. // Finalization: Finally, we have to set the stack size, which normally
  311. // would have to be computed on the fly and add a default constructor
  312. // method to the class, which is empty in this case.
  313. mg.addParameterAnnotation(0,createFruitAnnotation(cp,"Apples",true));
  314. mg.addParameterAnnotation(0,createFruitAnnotation(cp,"Oranges",true));
  315. mg.setMaxStack();
  316. mg.setMaxLocals();
  317. cg.addMethod(mg.getMethod());
  318. il.dispose(); // Allow instruction handles to be reused
  319. cg.addEmptyConstructor(Constants.ACC_PUBLIC);
  320. }
  321. private void buildClassContents(ClassGen cg, ConstantPool cp, InstructionList il) {
  322. // Create method 'public static void main(String[]argv)'
  323. MethodGen mg = createMethodGen("main",il,cp);
  324. InstructionFactory factory = new InstructionFactory(cg);
  325. // We now define some often used types:
  326. ObjectType i_stream = new ObjectType("java.io.InputStream");
  327. ObjectType p_stream = new ObjectType("java.io.PrintStream");
  328. // Create variables in and name : We call the constructors, i.e.,
  329. // execute BufferedReader(InputStreamReader(System.in)) . The reference
  330. // to the BufferedReader object stays on top of the stack and is stored
  331. // in the newly allocated in variable.
  332. il.append(factory.createNew("java.io.BufferedReader"));
  333. il.append(InstructionConstants.DUP); // Use predefined constant
  334. il.append(factory.createNew("java.io.InputStreamReader"));
  335. il.append(InstructionConstants.DUP);
  336. il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,Constants.GETSTATIC));
  337. il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
  338. Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
  339. il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
  340. Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
  341. Constants.INVOKESPECIAL));
  342. LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
  343. "java.io.BufferedReader"), null, null);
  344. int in = lg.getIndex();
  345. lg.setStart(il.append(InstructionFactory.createASTORE(in))); // "in" valid from here
  346. // Create local variable name and initialize it to null
  347. lg = mg.addLocalVariable("name", Type.STRING, null, null);
  348. int name = lg.getIndex();
  349. il.append(InstructionConstants.ACONST_NULL);
  350. lg.setStart(il.append(InstructionFactory.createASTORE(name))); // "name" valid from here
  351. // Create try-catch block: We remember the start of the block, read a
  352. // line from the standard input and store it into the variable name .
  353. // InstructionHandle try_start = il.append(factory.createFieldAccess(
  354. // "java.lang.System", "out", p_stream, Constants.GETSTATIC));
  355. // il.append(new PUSH(cp, "Please enter your name> "));
  356. // il.append(factory.createInvoke("java.io.PrintStream", "print",
  357. // Type.VOID, new Type[] { Type.STRING },
  358. // Constants.INVOKEVIRTUAL));
  359. // il.append(new ALOAD(in));
  360. // il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
  361. // Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
  362. InstructionHandle try_start = il.append(InstructionFactory.PUSH(cp,"Andy"));
  363. il.append(InstructionFactory.createASTORE(name));
  364. // Upon normal execution we jump behind exception handler, the target
  365. // address is not known yet.
  366. InstructionBranch g = new InstructionBranch(Constants.GOTO);
  367. InstructionHandle try_end = il.append(g);
  368. // We add the exception handler which simply returns from the method.
  369. LocalVariableGen var_ex = mg.addLocalVariable("ex",Type.getType("Ljava.io.IOException;"),null,null);
  370. int var_ex_slot = var_ex.getIndex();
  371. InstructionHandle handler = il.append(InstructionFactory.createASTORE(var_ex_slot));
  372. var_ex.setStart(handler);
  373. var_ex.setEnd(il.append(InstructionConstants.RETURN));
  374. mg.addExceptionHandler(try_start, try_end, handler,
  375. new ObjectType("java.io.IOException"));
  376. // "Normal" code continues, now we can set the branch target of the GOTO
  377. // .
  378. InstructionHandle ih = il.append(factory.createFieldAccess(
  379. "java.lang.System", "out", p_stream, Constants.GETSTATIC));
  380. g.setTarget(ih);
  381. // Printing "Hello": String concatenation compiles to StringBuffer
  382. // operations.
  383. il.append(factory.createNew(Type.STRINGBUFFER));
  384. il.append(InstructionConstants.DUP);
  385. il.append(InstructionFactory.PUSH(cp, "Hello, "));
  386. il
  387. .append(factory.createInvoke("java.lang.StringBuffer",
  388. "<init>", Type.VOID, new Type[] { Type.STRING },
  389. Constants.INVOKESPECIAL));
  390. il.append(InstructionFactory.createALOAD(name));
  391. il.append(factory.createInvoke("java.lang.StringBuffer", "append",
  392. Type.STRINGBUFFER, new Type[] { Type.STRING },
  393. Constants.INVOKEVIRTUAL));
  394. il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
  395. Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
  396. il.append(factory.createInvoke("java.io.PrintStream", "println",
  397. Type.VOID, new Type[] { Type.STRING },
  398. Constants.INVOKEVIRTUAL));
  399. il.append(InstructionConstants.RETURN);
  400. // Finalization: Finally, we have to set the stack size, which normally
  401. // would have to be computed on the fly and add a default constructor
  402. // method to the class, which is empty in this case.
  403. mg.setMaxStack();
  404. mg.setMaxLocals();
  405. cg.addMethod(mg.getMethod());
  406. il.dispose(); // Allow instruction handles to be reused
  407. cg.addEmptyConstructor(Constants.ACC_PUBLIC);
  408. }
  409. private JavaClass getClassFrom(String where,String clazzname) throws ClassNotFoundException {
  410. SyntheticRepository repos = createRepos(where);
  411. return repos.loadClass(clazzname);
  412. }
  413. // helper methods
  414. private ClassGen createClassGen(String classname) {
  415. return new ClassGen(classname, "java.lang.Object",
  416. "<generated>", Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
  417. }
  418. private MethodGen createMethodGen(String methodname,InstructionList il,ConstantPool cp) {
  419. return new MethodGen(
  420. Constants.ACC_STATIC | Constants.ACC_PUBLIC, // access flags
  421. Type.VOID, // return type
  422. new Type[] { new ArrayType(Type.STRING, 1) }, // argument types
  423. new String[] { "argv" }, // arg names
  424. methodname, "HelloWorld", // method, class
  425. il, cp);
  426. }
  427. public AnnotationGen createSimpleVisibleAnnotation(ConstantPool cp) {
  428. SimpleElementValue evg = new SimpleElementValue(
  429. ElementValue.PRIMITIVE_INT, cp, 4);
  430. NameValuePair nvGen = new NameValuePair("id", evg,cp);
  431. ObjectType t = new ObjectType("SimpleAnnotation");
  432. List<NameValuePair> elements = new ArrayList<NameValuePair>();
  433. elements.add(nvGen);
  434. AnnotationGen a = new AnnotationGen(t, elements,true, cp);
  435. return a;
  436. }
  437. public AnnotationGen createCombinedAnnotation(ConstantPool cp) {
  438. // Create an annotation instance
  439. AnnotationGen a = createSimpleVisibleAnnotation(cp);
  440. ArrayElementValue array = new ArrayElementValue(cp);
  441. array.addElement(new AnnotationElementValue(a,cp));
  442. NameValuePair nvp = new NameValuePair("value",array,cp);
  443. List<NameValuePair> elements = new ArrayList<NameValuePair>();
  444. elements.add(nvp);
  445. return new AnnotationGen(new ObjectType("CombinedAnnotation"),elements,true,cp);
  446. }
  447. public AnnotationGen createSimpleInvisibleAnnotation(ConstantPool cp) {
  448. SimpleElementValue evg = new SimpleElementValue(
  449. ElementValue.PRIMITIVE_INT, cp, 4);
  450. NameValuePair nvGen = new NameValuePair("id", evg,cp);
  451. ObjectType t = new ObjectType("SimpleAnnotation");
  452. List<NameValuePair> elements = new ArrayList<NameValuePair>();
  453. elements.add(nvGen);
  454. AnnotationGen a = new AnnotationGen(t, elements,false, cp);
  455. return a;
  456. }
  457. protected void tearDown() throws Exception {
  458. super.tearDown();
  459. }
  460. }