001    package railo.transformer.bytecode.visitor;
002    
003    import org.objectweb.asm.Label;
004    import org.objectweb.asm.Opcodes;
005    import org.objectweb.asm.Type;
006    import org.objectweb.asm.commons.GeneratorAdapter;
007    
008    import railo.transformer.bytecode.BytecodeContext;
009    import railo.transformer.bytecode.BytecodeException;
010    import railo.transformer.bytecode.statement.FlowControlFinal;
011    import railo.transformer.bytecode.util.ASMUtil;
012    import railo.transformer.bytecode.util.Types;
013    
014    public class TryCatchFinallyVisitor implements Opcodes {
015            private OnFinally onFinally;
016            private Label beginTry;
017            private Label endTry;
018            private Label endTry2;
019            private Label l3;
020            private Label l4;
021            private Label l5;
022            private Label l6;
023            private Type type=Types.THROWABLE;
024            private FlowControlFinal fcf;
025    
026    
027            public TryCatchFinallyVisitor(OnFinally onFinally, FlowControlFinal fcf){
028                    this.onFinally=onFinally;
029                    this.fcf=fcf;
030            }
031    
032            public void visitTryBegin(BytecodeContext bc) {
033                    GeneratorAdapter ga = bc.getAdapter();
034                    beginTry = new Label();
035                    endTry = new Label();
036                    endTry2 = new Label();
037                    l3 = new Label();
038                    l4 = new Label();
039                    bc.pushOnFinally(onFinally);
040                    ga.visitLabel(beginTry);
041            }
042    
043            public int visitTryEndCatchBeging(BytecodeContext bc) {
044                    GeneratorAdapter ga = bc.getAdapter();
045                    
046                    ga.visitTryCatchBlock(beginTry, endTry, endTry2, type.getInternalName());
047                    ga.visitLabel(endTry);
048                    l5 = new Label();
049                    ga.visitJumpInsn(GOTO, l5);
050                    ga.visitLabel(endTry2);
051                    int lThrow = ga.newLocal(type);
052                    ga.storeLocal(lThrow);
053                    //mv.visitVarInsn(ASTORE, 1);
054                    l6 = new Label();
055                    ga.visitLabel(l6);
056                    return lThrow;
057            }
058            
059            public void visitCatchEnd(BytecodeContext bc) throws BytecodeException {
060                    Label end = new Label();
061                    GeneratorAdapter ga = bc.getAdapter();
062                    bc.popOnFinally();
063                    ga.visitLabel(l3);
064                    ga.visitJumpInsn(GOTO, l5);
065                    ga.visitLabel(l4);
066                    int lThrow = ga.newLocal(Types.THROWABLE);
067                    ga.storeLocal(lThrow);
068                    //mv.visitVarInsn(ASTORE, 2);
069                    Label l8 = new Label();
070                    ga.visitLabel(l8);
071    
072                    onFinally.writeOut(bc);
073                    
074                    ga.loadLocal(lThrow);
075                    ga.visitInsn(ATHROW);
076                    ga.visitLabel(l5);
077    
078                    onFinally.writeOut(bc);
079                    if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null) {
080                            Label _end=new Label();
081                            ga.visitJumpInsn(Opcodes.GOTO, _end); // ignore when coming not from break/continue
082                                    ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel());
083                                    onFinally.writeOut(bc);
084                                    ga.visitJumpInsn(Opcodes.GOTO, fcf.getAfterFinalGOTOLabel());
085                            ga.visitLabel(_end);
086                    }
087                    
088                                    
089                    
090                    
091    
092                    ga.visitLabel(end);
093                    ga.visitTryCatchBlock(beginTry, l3, l4, null);
094                            
095            }
096    }