svn commit: r427943 [2/2] - in /jakarta/bcel/trunk/src: main/java/org/apache/bcel/classfile/ main/java/org/apache/bcel/generic/ test/java/org/apache/bcel/ test/java/org/apache/bcel/data/

[email protected] Wed, 02 Aug 2006 09:39:33 -0000
Newsgroups gmane.comp.jakarta.bcel.devel
Message-ID <[email protected]>
Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,609 @@
+package org.apache.bcel;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.bcel.classfile.AnnotationEntry;
+import org.apache.bcel.classfile.ElementValue;
+import org.apache.bcel.classfile.ElementValuePair;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.generic.ALOAD;
+import org.apache.bcel.generic.ASTORE;
+import org.apache.bcel.generic.AnnotationElementValueGen;
+import org.apache.bcel.generic.AnnotationEntryGen;
+import org.apache.bcel.generic.ArrayElementValueGen;
+import org.apache.bcel.generic.ArrayType;
+import org.apache.bcel.generic.ClassGen;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.ElementValueGen;
+import org.apache.bcel.generic.ElementValuePairGen;
+import org.apache.bcel.generic.GOTO;
+import org.apache.bcel.generic.InstructionConstants;
+import org.apache.bcel.generic.InstructionFactory;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.InstructionList;
+import org.apache.bcel.generic.LocalVariableGen;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.bcel.generic.ObjectType;
+import org.apache.bcel.generic.PUSH;
+import org.apache.bcel.generic.SimpleElementValueGen;
+import org.apache.bcel.generic.Type;
+import org.apache.bcel.util.SyntheticRepository;
+
+/**
+ * The program that some of the tests generate looks like this:
+ * 
+ * <pre>
+ * public class HelloWorld
+ * {
+ * 	public static void main(String[] argv)
+ * 	{
+ * 		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
+ * 		String name = null;
+ * 
+ * 		try
+ * 		{
+ * 			name = &quot;Andy&quot;;
+ * 		}
+ * 		catch (IOException e)
+ * 		{
+ * 			return;
+ * 		}
+ * 		System.out.println(&quot;Hello, &quot; + name);
+ * 	}
+ * }
+ * </pre>
+ */
+public class GeneratingAnnotatedClassesTestCase extends AbstractTestCase
+{
+	/**
+	 * Steps in the test:
+	 * <ol>
+	 * <li>Programmatically construct the HelloWorld program</li>
+	 * <li>Add two simple annotations at the class level</li>
+	 * <li>Save the class to disk</li>
+	 * <li>Reload the class using the 'static' variant of the BCEL classes</li>
+	 * <li>Check the attributes are OK</li>
+	 * </ol>
+	 */
+	public void testGenerateClassLevelAnnotations()
+			throws ClassNotFoundException
+	{
+		// Create HelloWorld
+		ClassGen cg = createClassGen("HelloWorld");
+		cg.setMajor(49);
+		cg.setMinor(0);
+		ConstantPoolGen cp = cg.getConstantPool();
+		InstructionList il = new InstructionList();
+		cg.addAnnotationEntry(createSimpleVisibleAnnotation(cp));
+		cg.addAnnotationEntry(createSimpleInvisibleAnnotation(cp));
+		buildClassContents(cg, cp, il);
+		//System.out.println(cg.getJavaClass().toString());
+		dumpClass(cg, "HelloWorld.class");
+		JavaClass jc = getClassFrom(".", "HelloWorld");
+		AnnotationEntry[] as = jc.getAnnotationEntries();
+		assertTrue("Should be two AnnotationEntries but found " + as.length,
+				as.length == 2);
+		AnnotationEntry one = as[0];
+		AnnotationEntry two = as[1];
+		// TODO L??;
+		assertTrue(
+				"Name of annotation 1 should be LSimpleAnnotation; but it is "
+						+ as[0].getAnnotationType(), as[0].getAnnotationType()
+						.equals("LSimpleAnnotation;"));
+		assertTrue(
+				"Name of annotation 2 should be LSimpleAnnotation; but it is "
+						+ as[1].getAnnotationType(), as[1].getAnnotationType()
+						.equals("LSimpleAnnotation;"));
+		ElementValuePair[] vals = as[0].getElementValuePairs();
+		ElementValuePair nvp = (ElementValuePair) vals[0];
+		assertTrue(
+				"Name of element in SimpleAnnotation should be 'id' but it is "
+						+ nvp.getNameString(), nvp.getNameString().equals("id"));
+		ElementValue ev = nvp.getValue();
+		assertTrue("Type of element value should be int but it is "
+				+ ev.getElementValueType(),
+				ev.getElementValueType() == ElementValue.PRIMITIVE_INT);
+		assertTrue("Value of element should be 4 but it is "
+				+ ev.stringifyValue(), ev.stringifyValue().equals("4"));
+		assertTrue(createTestdataFile("HelloWorld.class").delete());
+	}
+
+	/**
+	 * Just check that we can dump a class that has a method annotation on it
+	 * and it is still there when we read it back in
+	 */
+	public void testGenerateMethodLevelAnnotations1()
+			throws ClassNotFoundException
+	{
+		// Create HelloWorld
+		ClassGen cg = createClassGen("HelloWorld");
+		ConstantPoolGen cp = cg.getConstantPool();
+		InstructionList il = new InstructionList();
+		buildClassContentsWithAnnotatedMethods(cg, cp, il);
+		// Check annotation is OK
+		int i = cg.getMethods()[0].getAnnotationEntries().length;
+		assertTrue(
+				"Prior to dumping, main method should have 1 annotation but has "
+						+ i, i == 1);
+		dumpClass(cg, "temp1" + File.separator + "HelloWorld.class");
+		JavaClass jc2 = getClassFrom("temp1", "HelloWorld");
+		// Check annotation is OK
+		i = jc2.getMethods()[0].getAnnotationEntries().length;
+		assertTrue("JavaClass should say 1 annotation on main method but says "
+				+ i, i == 1);
+		ClassGen cg2 = new ClassGen(jc2);
+		// Check it now it is a ClassGen
+		Method[] m = cg2.getMethods();
+		i = m[0].getAnnotationEntries().length;
+		assertTrue("The main 'Method' should have one annotation but has " + i,
+				i == 1);
+		MethodGen mg = new MethodGen(m[0], cg2.getClassName(), cg2
+				.getConstantPool());
+		// Check it finally when the Method is changed to a MethodGen
+		i = mg.getAnnotationEntries().length;
+		assertTrue("The main 'MethodGen' should have one annotation but has "
+				+ i, i == 1);
+		assertTrue(wipe("temp1" + File.separator + "HelloWorld.class"));
+	}
+
+	/**
+	 * Going further than the last test - when we reload the method back in,
+	 * let's change it (adding a new annotation) and then store that, read it
+	 * back in and verify both annotations are there !
+	 */
+	public void testGenerateMethodLevelAnnotations2()
+			throws ClassNotFoundException
+	{
+		// Create HelloWorld
+		ClassGen cg = createClassGen("HelloWorld");
+		ConstantPoolGen cp = cg.getConstantPool();
+		InstructionList il = new InstructionList();
+		buildClassContentsWithAnnotatedMethods(cg, cp, il);
+		dumpClass(cg, "temp2", "HelloWorld.class");
+		JavaClass jc2 = getClassFrom("temp2", "HelloWorld");
+		ClassGen cg2 = new ClassGen(jc2);
+		// Main method after reading the class back in
+		Method mainMethod1 = jc2.getMethods()[0];
+		assertTrue("The 'Method' should have one annotations but has "
+				+ mainMethod1.getAnnotationEntries().length, mainMethod1
+				.getAnnotationEntries().length == 1);
+		MethodGen mainMethod2 = new MethodGen(mainMethod1, cg2.getClassName(),
+				cg2.getConstantPool());
+		assertTrue("The 'MethodGen' should have one annotations but has "
+				+ mainMethod2.getAnnotationEntries().length, mainMethod2
+				.getAnnotationEntries().length == 1);
+		mainMethod2.addAnnotationEntry(createFruitAnnotation(cg2
+				.getConstantPool(), "Pear"));
+		cg2.removeMethod(mainMethod1);
+		cg2.addMethod(mainMethod2.getMethod());
+		dumpClass(cg2, "temp3", "HelloWorld.class");
+		JavaClass jc3 = getClassFrom("temp3", "HelloWorld");
+		ClassGen cg3 = new ClassGen(jc3);
+		Method mainMethod3 = cg3.getMethods()[1];
+		int i = mainMethod3.getAnnotationEntries().length;
+		assertTrue("The 'Method' should now have two annotations but has " + i,
+				i == 2);
+		assertTrue(wipe("temp2", "HelloWorld.class"));
+		assertTrue(wipe("temp3", "HelloWorld.class"));
+	}
+
+	// J5TODO: Need to add deleteFile calls to many of these tests
+	/**
+	 * Transform simple class from an immutable to a mutable object.
+	 */
+	public void testTransformClassToClassGen_SimpleTypes()
+			throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.SimpleAnnotatedClass");
+		ClassGen cgen = new ClassGen(jc);
+		// Check annotations are correctly preserved
+		AnnotationEntryGen[] annotations = cgen.getAnnotationEntries();
+		assertTrue("Expected one annotation but found " + annotations.length,
+				annotations.length == 1);
+	}
+
+	/**
+	 * Transform simple class from an immutable to a mutable object. The class
+	 * is annotated with an annotation that uses an enum.
+	 */
+	public void testTransformClassToClassGen_EnumType()
+			throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.AnnotatedWithEnumClass");
+		ClassGen cgen = new ClassGen(jc);
+		// Check annotations are correctly preserved
+		AnnotationEntryGen[] annotations = cgen.getAnnotationEntries();
+		assertTrue("Expected one annotation but found " + annotations.length,
+				annotations.length == 1);
+	}
+
+	/**
+	 * Transform simple class from an immutable to a mutable object. The class
+	 * is annotated with an annotation that uses an array of SimpleAnnotations.
+	 */
+	public void testTransformClassToClassGen_ArrayAndAnnotationTypes()
+			throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.AnnotatedWithCombinedAnnotation");
+		ClassGen cgen = new ClassGen(jc);
+		// Check annotations are correctly preserved
+		AnnotationEntryGen[] annotations = cgen.getAnnotationEntries();
+		assertTrue("Expected one annotation but found " + annotations.length,
+				annotations.length == 1);
+		AnnotationEntryGen a = annotations[0];
+		assertTrue("That annotation should only have one value but has "
+				+ a.getValues().size(), a.getValues().size() == 1);
+		ElementValuePairGen nvp = (ElementValuePairGen) a.getValues().get(0);
+		ElementValueGen value = (ElementValueGen) nvp.getValue();
+		assertTrue("Value should be ArrayElementValueGen but is " + value,
+				value instanceof ArrayElementValueGen);
+		ArrayElementValueGen arrayValue = (ArrayElementValueGen) value;
+		assertTrue("Array value should be size one but is "
+				+ arrayValue.getElementValuesSize(), arrayValue
+				.getElementValuesSize() == 1);
+		ElementValueGen innerValue = (ElementValueGen) arrayValue
+				.getElementValues().get(0);
+		assertTrue(
+				"Value in the array should be AnnotationElementValueGen but is "
+						+ innerValue,
+				innerValue instanceof AnnotationElementValueGen);
+		AnnotationElementValueGen innerAnnotationValue = (AnnotationElementValueGen) innerValue;
+		assertTrue("Should be called LSimpleAnnotation; but is called: "
+				+ innerAnnotationValue.getAnnotation().getTypeName(),
+				innerAnnotationValue.getAnnotation().getTypeSignature().equals(
+						"LSimpleAnnotation;"));
+	}
+
+	/**
+	 * Transform complex class from an immutable to a mutable object.
+	 */
+	public void testTransformComplexClassToClassGen()
+			throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.ComplexAnnotatedClass");
+		ClassGen cgen = new ClassGen(jc);
+		// Check annotations are correctly preserved
+		AnnotationEntryGen[] annotations = cgen.getAnnotationEntries();
+		assertTrue("Expected one annotation but found " + annotations.length,
+				annotations.length == 1);
+		List l = annotations[0].getValues();
+		boolean found = false;
+		for (Iterator iter = l.iterator(); iter.hasNext();)
+		{
+			ElementValuePairGen element = (ElementValuePairGen) iter.next();
+			if (element.getNameString().equals("dval"))
+			{
+				if (((SimpleElementValueGen) element.getValue())
+						.stringifyValue().equals("33.4"))
+					found = true;
+			}
+		}
+		assertTrue("Did not find double annotation value with value 33.4",
+				found);
+	}
+
+	/**
+	 * Load a class in and modify it with a new attribute - A SimpleAnnotation
+	 * annotation
+	 */
+	public void testModifyingClasses1() throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.SimpleAnnotatedClass");
+		ClassGen cgen = new ClassGen(jc);
+		ConstantPoolGen cp = cgen.getConstantPool();
+		cgen.addAnnotationEntry(createFruitAnnotation(cp, "Pineapple"));
+		assertTrue("Should now have two annotations but has "
+				+ cgen.getAnnotationEntries().length, cgen
+				.getAnnotationEntries().length == 2);
+		dumpClass(cgen, "SimpleAnnotatedClass.class");
+		assertTrue(wipe("SimpleAnnotatedClass.class"));
+	}
+
+	/**
+	 * Load a class in and modify it with a new attribute - A ComplexAnnotation
+	 * annotation
+	 */
+	public void testModifyingClasses2() throws ClassNotFoundException
+	{
+		JavaClass jc = getTestClass("org.apache.bcel.data.SimpleAnnotatedClass");
+		ClassGen cgen = new ClassGen(jc);
+		ConstantPoolGen cp = cgen.getConstantPool();
+		cgen.addAnnotationEntry(createCombinedAnnotation(cp));
+		assertTrue("Should now have two annotations but has "
+				+ cgen.getAnnotationEntries().length, cgen
+				.getAnnotationEntries().length == 2);
+		dumpClass(cgen, "SimpleAnnotatedClass.class");
+		JavaClass jc2 = getClassFrom(".", "SimpleAnnotatedClass");
+		jc2.getAnnotationEntries();
+		assertTrue(wipe("SimpleAnnotatedClass.class"));
+		// System.err.println(jc2.toString());
+	}
+
+	private void dumpClass(ClassGen cg, String fname)
+	{
+		try
+		{
+			File f = createTestdataFile(fname);
+			cg.getJavaClass().dump(f);
+		}
+		catch (java.io.IOException e)
+		{
+			System.err.println(e);
+		}
+	}
+
+	private void dumpClass(ClassGen cg, String dir, String fname)
+	{
+		dumpClass(cg, dir + File.separator + fname);
+	}
+
+	private void buildClassContentsWithAnnotatedMethods(ClassGen cg,
+			ConstantPoolGen cp, InstructionList il)
+	{
+		// Create method 'public static void main(String[]argv)'
+		MethodGen mg = createMethodGen("main", il, cp);
+		InstructionFactory factory = new InstructionFactory(cg);
+		mg.addAnnotationEntry(createSimpleVisibleAnnotation(mg
+				.getConstantPool()));
+		// We now define some often used types:
+		ObjectType i_stream = new ObjectType("java.io.InputStream");
+		ObjectType p_stream = new ObjectType("java.io.PrintStream");
+		// Create variables in and name : We call the constructors, i.e.,
+		// execute BufferedReader(InputStreamReader(System.in)) . The reference
+		// to the BufferedReader object stays on top of the stack and is stored
+		// in the newly allocated in variable.
+		il.append(factory.createNew("java.io.BufferedReader"));
+		il.append(InstructionConstants.DUP); // Use predefined constant
+		il.append(factory.createNew("java.io.InputStreamReader"));
+		il.append(InstructionConstants.DUP);
+		il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,
+				Constants.GETSTATIC));
+		il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
+				Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
+		il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
+				Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
+				Constants.INVOKESPECIAL));
+		LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
+				"java.io.BufferedReader"), null, null);
+		int in = lg.getIndex();
+		lg.setStart(il.append(new ASTORE(in))); // "in" valid from here
+		// Create local variable name and initialize it to null
+		lg = mg.addLocalVariable("name", Type.STRING, null, null);
+		int name = lg.getIndex();
+		il.append(InstructionConstants.ACONST_NULL);
+		lg.setStart(il.append(new ASTORE(name))); // "name" valid from here
+		// Create try-catch block: We remember the start of the block, read a
+		// line from the standard input and store it into the variable name .
+		// InstructionHandle try_start = il.append(factory.createFieldAccess(
+		// "java.lang.System", "out", p_stream, Constants.GETSTATIC));
+		// il.append(new PUSH(cp, "Please enter your name> "));
+		// il.append(factory.createInvoke("java.io.PrintStream", "print",
+		// Type.VOID, new Type[] { Type.STRING },
+		// Constants.INVOKEVIRTUAL));
+		// il.append(new ALOAD(in));
+		// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
+		// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		InstructionHandle try_start = il.append(new PUSH(cp, "Andy"));
+		il.append(new ASTORE(name));
+		// Upon normal execution we jump behind exception handler, the target
+		// address is not known yet.
+		GOTO g = new GOTO(null);
+		InstructionHandle try_end = il.append(g);
+		// We add the exception handler which simply returns from the method.
+		LocalVariableGen var_ex = mg.addLocalVariable("ex", Type
+				.getType("Ljava.io.IOException;"), null, null);
+		int var_ex_slot = var_ex.getIndex();
+		InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
+		var_ex.setStart(handler);
+		var_ex.setEnd(il.append(InstructionConstants.RETURN));
+		mg.addExceptionHandler(try_start, try_end, handler, new ObjectType(
+				"java.io.IOException"));
+		// "Normal" code continues, now we can set the branch target of the GOTO
+		// .
+		InstructionHandle ih = il.append(factory.createFieldAccess(
+				"java.lang.System", "out", p_stream, Constants.GETSTATIC));
+		g.setTarget(ih);
+		// Printing "Hello": String concatenation compiles to StringBuffer
+		// operations.
+		il.append(factory.createNew(Type.STRINGBUFFER));
+		il.append(InstructionConstants.DUP);
+		il.append(new PUSH(cp, "Hello, "));
+		il
+				.append(factory.createInvoke("java.lang.StringBuffer",
+						"<init>", Type.VOID, new Type[] { Type.STRING },
+						Constants.INVOKESPECIAL));
+		il.append(new ALOAD(name));
+		il.append(factory.createInvoke("java.lang.StringBuffer", "append",
+				Type.STRINGBUFFER, new Type[] { Type.STRING },
+				Constants.INVOKEVIRTUAL));
+		il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
+				Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		il
+				.append(factory.createInvoke("java.io.PrintStream", "println",
+						Type.VOID, new Type[] { Type.STRING },
+						Constants.INVOKEVIRTUAL));
+		il.append(InstructionConstants.RETURN);
+		// Finalization: Finally, we have to set the stack size, which normally
+		// would have to be computed on the fly and add a default constructor
+		// method to the class, which is empty in this case.
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		cg.addMethod(mg.getMethod());
+		il.dispose(); // Allow instruction handles to be reused
+		cg.addEmptyConstructor(Constants.ACC_PUBLIC);
+	}
+
+	private void buildClassContents(ClassGen cg, ConstantPoolGen cp,
+			InstructionList il)
+	{
+		// Create method 'public static void main(String[]argv)'
+		MethodGen mg = createMethodGen("main", il, cp);
+		InstructionFactory factory = new InstructionFactory(cg);
+		// We now define some often used types:
+		ObjectType i_stream = new ObjectType("java.io.InputStream");
+		ObjectType p_stream = new ObjectType("java.io.PrintStream");
+		// Create variables in and name : We call the constructors, i.e.,
+		// execute BufferedReader(InputStreamReader(System.in)) . The reference
+		// to the BufferedReader object stays on top of the stack and is stored
+		// in the newly allocated in variable.
+		il.append(factory.createNew("java.io.BufferedReader"));
+		il.append(InstructionConstants.DUP); // Use predefined constant
+		il.append(factory.createNew("java.io.InputStreamReader"));
+		il.append(InstructionConstants.DUP);
+		il.append(factory.createFieldAccess("java.lang.System", "in", i_stream,
+				Constants.GETSTATIC));
+		il.append(factory.createInvoke("java.io.InputStreamReader", "<init>",
+				Type.VOID, new Type[] { i_stream }, Constants.INVOKESPECIAL));
+		il.append(factory.createInvoke("java.io.BufferedReader", "<init>",
+				Type.VOID, new Type[] { new ObjectType("java.io.Reader") },
+				Constants.INVOKESPECIAL));
+		LocalVariableGen lg = mg.addLocalVariable("in", new ObjectType(
+				"java.io.BufferedReader"), null, null);
+		int in = lg.getIndex();
+		lg.setStart(il.append(new ASTORE(in))); // "in" valid from here
+		// Create local variable name and initialize it to null
+		lg = mg.addLocalVariable("name", Type.STRING, null, null);
+		int name = lg.getIndex();
+		il.append(InstructionConstants.ACONST_NULL);
+		lg.setStart(il.append(new ASTORE(name))); // "name" valid from here
+		// Create try-catch block: We remember the start of the block, read a
+		// line from the standard input and store it into the variable name .
+		// InstructionHandle try_start = il.append(factory.createFieldAccess(
+		// "java.lang.System", "out", p_stream, Constants.GETSTATIC));
+		// il.append(new PUSH(cp, "Please enter your name> "));
+		// il.append(factory.createInvoke("java.io.PrintStream", "print",
+		// Type.VOID, new Type[] { Type.STRING },
+		// Constants.INVOKEVIRTUAL));
+		// il.append(new ALOAD(in));
+		// il.append(factory.createInvoke("java.io.BufferedReader", "readLine",
+		// Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		InstructionHandle try_start = il.append(new PUSH(cp, "Andy"));
+		il.append(new ASTORE(name));
+		// Upon normal execution we jump behind exception handler, the target
+		// address is not known yet.
+		GOTO g = new GOTO(null);
+		InstructionHandle try_end = il.append(g);
+		// We add the exception handler which simply returns from the method.
+		LocalVariableGen var_ex = mg.addLocalVariable("ex", Type
+				.getType("Ljava.io.IOException;"), null, null);
+		int var_ex_slot = var_ex.getIndex();
+		InstructionHandle handler = il.append(new ASTORE(var_ex_slot));
+		var_ex.setStart(handler);
+		var_ex.setEnd(il.append(InstructionConstants.RETURN));
+		mg.addExceptionHandler(try_start, try_end, handler, new ObjectType(
+				"java.io.IOException"));
+		// "Normal" code continues, now we can set the branch target of the GOTO
+		// .
+		InstructionHandle ih = il.append(factory.createFieldAccess(
+				"java.lang.System", "out", p_stream, Constants.GETSTATIC));
+		g.setTarget(ih);
+		// Printing "Hello": String concatenation compiles to StringBuffer
+		// operations.
+		il.append(factory.createNew(Type.STRINGBUFFER));
+		il.append(InstructionConstants.DUP);
+		il.append(new PUSH(cp, "Hello, "));
+		il
+				.append(factory.createInvoke("java.lang.StringBuffer",
+						"<init>", Type.VOID, new Type[] { Type.STRING },
+						Constants.INVOKESPECIAL));
+		il.append(new ALOAD(name));
+		il.append(factory.createInvoke("java.lang.StringBuffer", "append",
+				Type.STRINGBUFFER, new Type[] { Type.STRING },
+				Constants.INVOKEVIRTUAL));
+		il.append(factory.createInvoke("java.lang.StringBuffer", "toString",
+				Type.STRING, Type.NO_ARGS, Constants.INVOKEVIRTUAL));
+		il
+				.append(factory.createInvoke("java.io.PrintStream", "println",
+						Type.VOID, new Type[] { Type.STRING },
+						Constants.INVOKEVIRTUAL));
+		il.append(InstructionConstants.RETURN);
+		// Finalization: Finally, we have to set the stack size, which normally
+		// would have to be computed on the fly and add a default constructor
+		// method to the class, which is empty in this case.
+		mg.setMaxStack();
+		mg.setMaxLocals();
+		cg.addMethod(mg.getMethod());
+		il.dispose(); // Allow instruction handles to be reused
+		cg.addEmptyConstructor(Constants.ACC_PUBLIC);
+	}
+
+	private JavaClass getClassFrom(String where, String clazzname)
+			throws ClassNotFoundException
+	{
+		// System.out.println(where);
+		SyntheticRepository repos = createRepos(where);
+		return repos.loadClass(clazzname);
+	}
+
+	// helper methods
+	private ClassGen createClassGen(String classname)
+	{
+		return new ClassGen(classname, "java.lang.Object", "<generated>",
+				Constants.ACC_PUBLIC | Constants.ACC_SUPER, null);
+	}
+
+	private MethodGen createMethodGen(String methodname, InstructionList il,
+			ConstantPoolGen cp)
+	{
+		return new MethodGen(Constants.ACC_STATIC | Constants.ACC_PUBLIC, // access
+				// flags
+				Type.VOID, // return type
+				new Type[] { new ArrayType(Type.STRING, 1) }, // argument
+				// types
+				new String[] { "argv" }, // arg names
+				methodname, "HelloWorld", // method, class
+				il, cp);
+	}
+
+	public AnnotationEntryGen createSimpleVisibleAnnotation(ConstantPoolGen cp)
+	{
+		SimpleElementValueGen evg = new SimpleElementValueGen(
+				ElementValueGen.PRIMITIVE_INT, cp, 4);
+		ElementValuePairGen nvGen = new ElementValuePairGen("id", evg, cp);
+		ObjectType t = new ObjectType("SimpleAnnotation");
+		List elements = new ArrayList();
+		elements.add(nvGen);
+		AnnotationEntryGen a = new AnnotationEntryGen(t, elements, true, cp);
+		return a;
+	}
+
+	public AnnotationEntryGen createFruitAnnotation(ConstantPoolGen cp,
+			String aFruit)
+	{
+		SimpleElementValueGen evg = new SimpleElementValueGen(
+				ElementValueGen.STRING, cp, aFruit);
+		ElementValuePairGen nvGen = new ElementValuePairGen("fruit", evg, cp);
+		ObjectType t = new ObjectType("SimpleStringAnnotation");
+		List elements = new ArrayList();
+		elements.add(nvGen);
+		return new AnnotationEntryGen(t, elements, true, cp);
+	}
+
+	public AnnotationEntryGen createCombinedAnnotation(ConstantPoolGen cp)
+	{
+		// Create an annotation instance
+		AnnotationEntryGen a = createSimpleVisibleAnnotation(cp);
+		ArrayElementValueGen array = new ArrayElementValueGen(cp);
+		array.addElement(new AnnotationElementValueGen(a, cp));
+		ElementValuePairGen nvp = new ElementValuePairGen("value", array, cp);
+		List elements = new ArrayList();
+		elements.add(nvp);
+		return new AnnotationEntryGen(new ObjectType("CombinedAnnotation"),
+				elements, true, cp);
+	}
+
+	public AnnotationEntryGen createSimpleInvisibleAnnotation(ConstantPoolGen cp)
+	{
+		SimpleElementValueGen evg = new SimpleElementValueGen(
+				ElementValueGen.PRIMITIVE_INT, cp, 4);
+		ElementValuePairGen nvGen = new ElementValuePairGen("id", evg, cp);
+		ObjectType t = new ObjectType("SimpleAnnotation");
+		List elements = new ArrayList();
+		elements.add(nvGen);
+		AnnotationEntryGen a = new AnnotationEntryGen(t, elements, false, cp);
+		return a;
+	}
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/GeneratingAnnotatedClassesTestCase.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,7 @@
+package org.apache.bcel.data;
+
+public class AnnotatedFields {
+  @SimpleAnnotation(id=1) int i;
+
+  @SimpleAnnotation(id=2) String s;
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedFields.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,6 @@
+package org.apache.bcel.data;
+
+@CombinedAnnotation( { @SimpleAnnotation(id = 4) })
+public class AnnotatedWithCombinedAnnotation
+{
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithCombinedAnnotation.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,6 @@
+package org.apache.bcel.data;
+
+@AnnotationEnumElement(enumval = SimpleEnum.Red)
+public class AnnotatedWithEnumClass
+{
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotatedWithEnumClass.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,10 @@
+package org.apache.bcel.data;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface AnnotationEnumElement
+{
+	SimpleEnum enumval();
+}
\ No newline at end of file

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnnotationEnumElement.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,22 @@
+package org.apache.bcel.data;
+
+public class AnonymousClassTest
+{
+	public void foo()
+	{
+		new Runnable()
+		{
+			public void run()
+			{
+			};
+		}.run();
+	}
+
+	class X
+	{
+	}
+
+	static class Y
+	{
+	}
+}
\ No newline at end of file

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AnonymousClassTest.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,15 @@
+package org.apache.bcel.data;
+
+public class AttributeTestClassEM01
+{
+	public static void main(String[] argv)
+	{
+		class S
+		{
+			public void sayhello()
+			{
+				System.err.println("hello");
+			}
+		}
+	}
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM01.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,16 @@
+package org.apache.bcel.data;
+
+public class AttributeTestClassEM02
+{
+	Runnable r = new Runnable()
+	{
+		public void run()
+		{
+			System.err.println("hello");
+		}
+	};
+
+	public static void main(String[] argv)
+	{
+	}
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/AttributeTestClassEM02.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,10 @@
+package org.apache.bcel.data;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface CombinedAnnotation
+{
+	public SimpleAnnotation[] value();
+}
\ No newline at end of file

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/CombinedAnnotation.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,6 @@
+package org.apache.bcel.data;
+
+@ComplexAnnotation(ival = 4, bval = 2, cval = '5', fval = 3.0f, dval = 33.4, zval = false, jval = 56, sval = 99)
+public class ComplexAnnotatedClass
+{
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotatedClass.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,24 @@
+package org.apache.bcel.data;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ComplexAnnotation
+{
+	int ival();
+
+	byte bval();
+
+	char cval();
+
+	long jval();
+
+	double dval();
+
+	boolean zval();
+
+	short sval();
+
+	float fval();
+}
\ No newline at end of file

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/ComplexAnnotation.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"

Added: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java
URL: http://svn.apache.org/viewvc/jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java?rev=427943&view=auto
==============================================================================
--- jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java (added)
+++ jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java Wed Aug  2 02:39:32 2006
@@ -0,0 +1,6 @@
+package org.apache.bcel.data;
+
+@SimpleAnnotation(id = 4)
+public class SimpleAnnotatedClass
+{
+}

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/bcel/trunk/src/test/java/org/apache/bcel/data/SimpleAnnotatedClass.java
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Revision"