All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.amygdalum.testrecorder.asm.WrapWithTryCatch Maven / Gradle / Ivy

The newest version!
package net.amygdalum.testrecorder.asm;

import static org.objectweb.asm.Opcodes.ATHROW;
import static org.objectweb.asm.Opcodes.GOTO;
import static org.objectweb.asm.Opcodes.IRETURN;
import static org.objectweb.asm.Opcodes.RETURN;

import java.util.ListIterator;

import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.TryCatchBlockNode;

public class WrapWithTryCatch implements SequenceInstruction {

	private LabelNode tryLabel;
	private LabelNode catchLabel;
	private LabelNode returnLabel;

	private SequenceInstruction tryInstructions;
	private SequenceInstruction catchInstructions;
	private SequenceInstruction returnInstructions;

	public WrapWithTryCatch() {
		this.tryLabel = new LabelNode();
		this.catchLabel = new LabelNode();
		this.returnLabel = new LabelNode();
	}

	public WrapWithTryCatch before(SequenceInstruction tryInstructions) {
		this.tryInstructions = tryInstructions;
		return this;
	}

	public WrapWithTryCatch after(SequenceInstruction returnInstructions) {
		this.returnInstructions = returnInstructions;
		return this;
	}
	
	public WrapWithTryCatch handler(SequenceInstruction catchInstructions) {
		this.catchInstructions = catchInstructions;
		return this;
	}

	@Override
	public InsnList build(MethodContext context) {
		Type returnType = context.getResultType();

		context.tryCatchBlocks().add(new TryCatchBlockNode(tryLabel, catchLabel, catchLabel, null));

		InsnList insnList = new InsnList();
		insnList.add(tryLabel);
		insnList.add(tryInstructions.build(context));
		
		ListIterator instructions = context.instructions().iterator();
		while (instructions.hasNext()) {
			AbstractInsnNode insn = instructions.next();
			if (isReturn(insn)) {
				insnList.add(new JumpInsnNode(GOTO, returnLabel));
			} else {
				insnList.add(insn);
			}
		}
		insnList.add(returnLabel);
		insnList.add(returnInstructions.build(context));
		insnList.add(new InsnNode(returnType.getOpcode(IRETURN)));
		insnList.add(catchLabel);
		insnList.add(catchInstructions.build(context));
		insnList.add(new InsnNode(ATHROW));
		
		return insnList;
	}

	private boolean isReturn(AbstractInsnNode insn) {
		return IRETURN <= insn.getOpcode() && insn.getOpcode() <= RETURN;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy