Package railo.transformer.bytecode.statement

Source Code of railo.transformer.bytecode.statement.TryCatchFinally$Catch

package railo.transformer.bytecode.statement;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

import railo.runtime.type.scope.Scope;
import railo.transformer.bytecode.Body;
import railo.transformer.bytecode.BytecodeContext;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.expression.ExprString;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.expression.var.DataMember;
import railo.transformer.bytecode.expression.var.Variable;
import railo.transformer.bytecode.expression.var.VariableRef;
import railo.transformer.bytecode.expression.var.VariableString;
import railo.transformer.bytecode.literal.LitBoolean;
import railo.transformer.bytecode.literal.LitString;
import railo.transformer.bytecode.statement.tag.TagTry;
import railo.transformer.bytecode.util.ExpressionUtil;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.OnFinally;
import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor;

/**
* produce  try-catch-finally
*/
public final class TryCatchFinally extends StatementBase implements Opcodes,HasBodies,FlowControlRetry {

  //private static LitString ANY=LitString.toExprString("any", -1);
 
  private static final Method TO_PAGE_EXCEPTION = new Method(
      "toPageException",
      Types.PAGE_EXCEPTION,
      new Type[]{Types.THROWABLE});
 
 
 
  //  public boolean typeEqual(String type);
  private static final Method TYPE_EQUAL = new Method(
      "typeEqual",
      Types.BOOLEAN_VALUE,
      new Type[]{Types.STRING});
 
 
  // Struct getCatchBlock(PageContext pc);
  private static final Method GET_CATCH_BLOCK = new Method(
      "getCatchBlock",
      Types.STRUCT,
      new Type[]{Types.PAGE_CONTEXT});


  // void isAbort(e)
  public static final Method IS_ABORT = new Method(
      "isAbort",
      Types.BOOLEAN_VALUE,
      new Type[]{Types.THROWABLE});

 

  private final static Method SET = new Method("set",Types.OBJECT,new Type[]{Types.PAGE_CONTEXT,Types.OBJECT});

  private static final Method REMOVE_EL = new Method("removeEL",Types.OBJECT,new Type[]{Types.PAGE_CONTEXT});
 
 
 
 
  private Body tryBody;
  private Body finallyBody;
  private List<Catch> catches=new ArrayList<Catch>();
  private Position finallyLine;


  private Label begin = new Label();

  private FlowControlFinal fcf;


  /**
   * Constructor of the class
   * @param body
   * @param line
   */
  public TryCatchFinally(Body body,Position start, Position end) {
    super(start,end);
    this.tryBody=body;
    body.setParent(this);
  }

  /**
   * sets finally body
   * @param body
   */
  public void setFinally(Body body, Position finallyLine) {
    body.setParent(this);
    this.finallyBody=body;
    this.finallyLine=finallyLine;
  }

  /**
   * data for a single catch block
   */
  private class Catch {

    private ExprString type;
    private Body body;
    private VariableRef name;
    private Position line;

    public Catch(ExprString type, VariableRef name, Body body, Position line) {
      this.type=type;
      this.name=name;
      this.body=body;
      this.line=line;
    }
   
  }
 
 
 
  /**
   *
   * @see railo.transformer.bytecode.statement.StatementBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
   */
  public void _writeOut(BytecodeContext bc) throws BytecodeException {
    GeneratorAdapter adapter = bc.getAdapter();
   
    adapter.visitLabel(begin);
   
    // Reference ref=null;
    final int lRef=adapter.newLocal(Types.REFERENCE);
    adapter.visitInsn(Opcodes.ACONST_NULL);
    adapter.storeLocal(lRef);
   
    // has no try body, if there is no try body, no catches are executed, only finally
    if(!tryBody.hasStatements()) {
      if(finallyBody!=null)finallyBody.writeOut(bc);
      return;
    }
   
   
    TryCatchFinallyVisitor tcfv=new TryCatchFinallyVisitor(new OnFinally() {
     
      public void writeOut(BytecodeContext bc) throws BytecodeException {
        _writeOutFinally(bc,lRef);
      }
    },getFlowControlFinal());

    // try
    tcfv.visitTryBegin(bc);
      tryBody.writeOut(bc);
    int lThrow = tcfv.visitTryEndCatchBeging(bc);
      _writeOutCatch(bc, lRef, lThrow);
    tcfv.visitCatchEnd(bc);
   
  }
 
 
 
 
 
 
 
 
  private void _writeOutFinally(BytecodeContext bc, int lRef) throws BytecodeException {
    // ref.remove(pc);
    //Reference r=null;
    GeneratorAdapter adapter = bc.getAdapter();
   
    //if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null)ASMUtil.visitLabel(adapter,fcf.getFinalEntryLabel());
    ExpressionUtil.visitLine(bc, finallyLine);
   
   
   
    //if (reference != null)
    //    reference.removeEL(pagecontext);
    Label removeEnd=new Label();
    adapter.loadLocal(lRef);
    adapter.ifNull(removeEnd);
      adapter.loadLocal(lRef);
      adapter.loadArg(0);
      adapter.invokeInterface(Types.REFERENCE, REMOVE_EL);
      adapter.pop();
    adapter.visitLabel(removeEnd);
   
    if(finallyBody!=null)finallyBody.writeOut(bc); // finally
    /*if(fcf!=null){
      Label l = fcf.getAfterFinalGOTOLabel();
      if(l!=null)adapter.visitJumpInsn(Opcodes.GOTO, l);
    }*/
  }
 
  private void _writeOutCatch(BytecodeContext bc, int lRef,int lThrow) throws BytecodeException {
    GeneratorAdapter adapter = bc.getAdapter();
    int pe=adapter.newLocal(Types.PAGE_EXCEPTION);
   
   
    // instance of Abort
      Label abortEnd=new Label();
      adapter.loadLocal(lThrow);
      adapter.invokeStatic(Types.ABORT, TryCatchFinally.IS_ABORT);
      //adapter.instanceOf(Types.ABORT);
          adapter.ifZCmp(Opcodes.IFEQ, abortEnd);
          adapter.loadLocal(lThrow);
          adapter.throwException();
          adapter.visitLabel(abortEnd);


          // PageExceptionImpl old=pc.getCatch();
          int old=adapter.newLocal(Types.PAGE_EXCEPTION);
          adapter.loadArg(0);
          adapter.invokeVirtual(Types.PAGE_CONTEXT, TagTry.GET_CATCH);
      adapter.storeLocal(old);
         
         
      // cast to PageException  Caster.toPagException(t);
          adapter.loadLocal(lThrow);
          adapter.invokeStatic(Types.CASTER, TO_PAGE_EXCEPTION);
         
      // PageException pe=...
          adapter.storeLocal(pe);

      // catch loop
      Label endAllIf = new Label();
          Iterator<Catch> it = catches.iterator();
          Catch ctElse=null;
      while(it.hasNext()) {
        Catch ct=it.next();
        // store any for else
        if(ct.type!=null && ct.type instanceof LitString && ((LitString)ct.type).getString().equalsIgnoreCase("any")){
          ctElse=ct;
          continue;
        }
       
        ExpressionUtil.visitLine(bc, ct.line);
       
        // pe.typeEqual(type)
        if(ct.type==null){
          LitBoolean.TRUE.writeOut(bc, Expression.MODE_VALUE);
        }
        else {
          adapter.loadLocal(pe);
          ct.type.writeOut(bc, Expression.MODE_REF);
          adapter.invokeVirtual(Types.PAGE_EXCEPTION, TYPE_EQUAL);
        }
       
       
       

        Label endIf = new Label();
              adapter.ifZCmp(Opcodes.IFEQ, endIf);
             
              catchBody(bc,adapter,ct,pe,lRef,true,true);
             
              adapter.visitJumpInsn(Opcodes.GOTO, endAllIf);
              adapter.visitLabel(endIf);
             

       
      }
     
      if(ctElse!=null){
        catchBody(bc,adapter,ctElse,pe,lRef,true,true);
      }
      else{
      // pc.setCatch(pe,true);
        adapter.loadArg(0);
            adapter.loadLocal(pe);
            adapter.push(false);
            adapter.push(false);
            adapter.invokeVirtual(Types.PAGE_CONTEXT, TagTry.SET_CATCH3);
             
       
        adapter.loadLocal(pe);
        adapter.throwException();
      }
      adapter.visitLabel(endAllIf);
     
        // PageExceptionImpl old=pc.setCatch(old);
            adapter.loadArg(0);
            adapter.loadLocal(old);
            adapter.invokeVirtual(Types.PAGE_CONTEXT, TagTry.SET_CATCH_PE);
     
  }

  private static void catchBody(BytecodeContext bc, GeneratorAdapter adapter, Catch ct, int pe, int lRef,boolean caugth,boolean store) throws BytecodeException {
    // pc.setCatch(pe,true);
    adapter.loadArg(0);
        adapter.loadLocal(pe);
        adapter.push(caugth);
        adapter.push(store);
        adapter.invokeVirtual(Types.PAGE_CONTEXT, TagTry.SET_CATCH3);
       
       
        // ref=
        ct.name.writeOut(bc, Expression.MODE_REF);
        adapter.storeLocal(lRef);
       
    adapter.loadLocal(lRef);
    adapter.loadArg(0);
    adapter.loadLocal(pe);// (...,pe.getCatchBlock(pc))
    adapter.loadArg(0);
        adapter.invokeVirtual(Types.PAGE_EXCEPTION, GET_CATCH_BLOCK);
    adapter.invokeInterface(Types.REFERENCE, SET);
    adapter.pop();
      
        ct.body.writeOut(bc);
  }

  /**
   * @param type
   * @param name
   * @param body
   * @param line
   */
  public void addCatch(ExprString type, VariableRef name, Body body, Position line) {
    body.setParent(this);
    catches.add(new Catch(type,name,body,line));
  }

  /**
   * @param type
   * @param name
   * @param b
   * @param line
   * @throws BytecodeException
   */
  public void addCatch(Expression type, Expression name, Body b, Position line) throws BytecodeException {
   
    // type
    if(type==null || type instanceof ExprString) ;
    else if(type instanceof Variable) {
      type=VariableString.toExprString(type);
    }
    else throw new BytecodeException("type from catch statement is invalid",type.getStart());
   
    // name
    if(name instanceof LitString){
      Variable v = new Variable(Scope.SCOPE_UNDEFINED,name.getStart(),name.getEnd());
      v.addMember(new DataMember(name));
      name=new VariableRef(v);
    }
    else if(name instanceof Variable) name=new VariableRef((Variable) name);
    else throw new BytecodeException("name from catch statement is invalid",name.getStart());
   
    addCatch((ExprString)type, (VariableRef)name, b, line);
 
 

  /**
   * @see railo.transformer.bytecode.statement.HasBodies#getBodies()
   */
  public Body[] getBodies() {
   
    int len=catches.size(),count=0;
    if(tryBody!=null)len++;
    if(finallyBody!=null)len++;
    Body[] bodies=new Body[len];
    Catch c;
    Iterator<Catch> it = catches.iterator();
    while(it.hasNext()) {
      c=it.next();
      bodies[count++]=c.body;
    }
    if(tryBody!=null)bodies[count++]=tryBody;
    if(finallyBody!=null)bodies[count++]=finallyBody;
   
    return bodies;
  }

  @Override
  public FlowControlFinal getFlowControlFinal() {
    if(fcf==null) fcf=new FlowControlFinalImpl();
    return fcf;
  }

  @Override
  public Label getRetryLabel() {
    return begin;
  }

  @Override
  public String getLabel() {
    return null;
  }
}
TOP

Related Classes of railo.transformer.bytecode.statement.TryCatchFinally$Catch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.