Package railo.transformer.bytecode.statement.tag

Source Code of railo.transformer.bytecode.statement.tag.TagTry

package railo.transformer.bytecode.statement.tag;

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.transformer.bytecode.Body;
import railo.transformer.bytecode.BodyBase;
import railo.transformer.bytecode.BytecodeContext;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.Statement;
import railo.transformer.bytecode.expression.ExprString;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.literal.LitString;
import railo.transformer.bytecode.statement.FlowControlFinal;
import railo.transformer.bytecode.statement.FlowControlFinalImpl;
import railo.transformer.bytecode.statement.FlowControlRetry;
import railo.transformer.bytecode.statement.TryCatchFinally;
import railo.transformer.bytecode.util.ExpressionUtil;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.OnFinally;
import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor;

public final class TagTry extends TagBase implements FlowControlRetry {

  private static final ExprString ANY=LitString.toExprString("any");

  private static final Method GET_VARIABLE = new Method(
      "getVariable",
      Types.OBJECT,
      new Type[]{Types.STRING});
 
  private static final Method TO_PAGE_EXCEPTION = new Method(
      "toPageException",
      Types.PAGE_EXCEPTION,
      new Type[]{Types.THROWABLE});
 
 
  public static final Method SET_CATCH_PE = new Method(
      "setCatch",
      Types.VOID,
      new Type[]{Types.PAGE_EXCEPTION});
 
  public static final Method SET_CATCH3 = new Method(
      "setCatch",
      Types.VOID,
      new Type[]{Types.PAGE_EXCEPTION,Types.BOOLEAN_VALUE,Types.BOOLEAN_VALUE});
 
  public static final Method GET_CATCH = new Method(
      "getCatch",
      Types.PAGE_EXCEPTION,
      new Type[]{});

  //  public boolean typeEqual(String type);
  private static final Method TYPE_EQUAL = new Method(
      "typeEqual",
      Types.BOOLEAN_VALUE,
      new Type[]{Types.STRING});

  private FlowControlFinal fcf;

  private boolean checked;
  private Label begin = new Label();

 
  public TagTry(Position start,Position end) {
    super(start,end);
  }

  /**
   *
   * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter)
   */
  public void _writeOut(BytecodeContext bc) throws BytecodeException {
    GeneratorAdapter adapter = bc.getAdapter();
    adapter.visitLabel(begin);
    Body tryBody=new BodyBase();
    List<Tag> catches=new ArrayList<Tag>();
    Tag tmpFinal=null;

    tryBody.setParent(getBody().getParent());
   
    List<Statement> statements = getBody().getStatements();
    Statement stat;
    Tag tag;
    {
    Iterator<Statement> it = statements.iterator();
    while(it.hasNext()) {
      stat= it.next();
      if(stat instanceof Tag) {
        tag=(Tag) stat;
        if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Catch"))  {
          catches.add(tag);
          continue;
        }
        else if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Finally"))  {
          tmpFinal=tag;
          continue;
        }
      }
      tryBody.addStatement(stat);
    };
    }
    final Tag _finally=tmpFinal;
   
    // has no try body, if there is no try body, no catches are executed, only finally
    if(!tryBody.hasStatements()) {
     
      if(_finally!=null && _finally.getBody()!=null)_finally.getBody().writeOut(bc);
      return;
    }
    TryCatchFinallyVisitor tcfv=new TryCatchFinallyVisitor(new OnFinally() {
     
      public void writeOut(BytecodeContext bc) throws BytecodeException {
        /*GeneratorAdapter ga = bc.getAdapter();
        if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null)
          ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel());
        */
        if(_finally!=null) {
         
          ExpressionUtil.visitLine(bc, _finally.getStart());
          _finally.getBody().writeOut(bc);
         
        }
        /*if(fcf!=null){
          Label l=fcf.getAfterFinalGOTOLabel();
          if(l!=null)ga.visitJumpInsn(Opcodes.GOTO, l);
        }*/
      }
    },getFlowControlFinal());
   
   
    // Try
    tcfv.visitTryBegin(bc);
      tryBody.writeOut(bc);
    int e=tcfv.visitTryEndCatchBeging(bc);
      // if(e instanceof railo.runtime.exp.Abort) throw e;
      Label abortEnd=new Label();
      adapter.loadLocal(e);
      // Abort.isAbort(t);
      adapter.invokeStatic(Types.ABORT, TryCatchFinally.IS_ABORT);
      //adapter.instanceOf(Types.ABORT);
     
     
     
          adapter.ifZCmp(Opcodes.IFEQ, abortEnd);
            adapter.loadLocal(e);
            adapter.throwException();
          adapter.visitLabel(abortEnd);
       

          // PageExceptionImpl old=pc.getCatch();
          int old=adapter.newLocal(Types.PAGE_EXCEPTION);
          adapter.loadArg(0);
          adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_CATCH);
      adapter.storeLocal(old);
     
          // PageException pe=Caster.toPageEception(e);
          int pe=adapter.newLocal(Types.PAGE_EXCEPTION);
          adapter.loadLocal(e);
          adapter.invokeStatic(Types.CASTER, TO_PAGE_EXCEPTION);
      adapter.storeLocal(pe);
     
      Iterator<Tag> it = catches.iterator();
      Attribute attrType;
      Expression type;
      Label endAllIfs=new Label();
      Tag tagElse=null;
      while(it.hasNext()) {
        tag=it.next();
        Label endIf=new Label();
        attrType = tag.getAttribute("type");
        type=ANY;
        if(attrType!=null)type=attrType.getValue();

        if(type instanceof LitString && ((LitString)type).getString().equalsIgnoreCase("any")){
          tagElse=tag;
          continue;
        }
       
        ExpressionUtil.visitLine(bc, tag.getStart());
       
        // if(pe.typeEqual(@type)
        adapter.loadLocal(pe);
        type.writeOut(bc, Expression.MODE_REF);
        adapter.invokeVirtual(Types.PAGE_EXCEPTION, TYPE_EQUAL);
       
        adapter.ifZCmp(Opcodes.IFEQ, endIf);
          catchBody(bc,adapter,tag,pe,true,true);
         
              adapter.visitJumpInsn(Opcodes.GOTO, endAllIfs);
             
              adapter.visitLabel(endIf);
       
       
      }
      // else
      if(tagElse!=null){
        catchBody(bc, adapter, tagElse, pe, true,true);
      }
      else{
        // pc.setCatch(pe,true);
        adapter.loadArg(0);
            adapter.loadLocal(pe);
            adapter.push(false);
            adapter.push(true);
            adapter.invokeVirtual(Types.PAGE_CONTEXT, SET_CATCH3);
       
        //throw pe;
        adapter.loadLocal(pe);
        adapter.throwException();
      }
      adapter.visitLabel(endAllIfs);
     
   
    // PageExceptionImpl old=pc.getCatch();
        adapter.loadArg(0);
        adapter.loadLocal(old);
        adapter.invokeVirtual(Types.PAGE_CONTEXT, SET_CATCH_PE);
     
    tcfv.visitCatchEnd(bc);
  }
 

  private static void catchBody(BytecodeContext bc, GeneratorAdapter adapter,Tag tag, int pe,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, SET_CATCH3);
    tag.getBody().writeOut(bc);
     
  }
 
  private boolean hasFinally(){
    List<Statement> statements = getBody().getStatements();
    Statement stat;
    Tag tag;
    Iterator<Statement> it = statements.iterator();
    while(it.hasNext()) {
      stat= it.next();
      if(stat instanceof Tag) {
        tag=(Tag) stat;
        if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Finally"))  {
          return true;
        }
      }
    }
    return false;
  }
 

  @Override
  public FlowControlFinal getFlowControlFinal() {
    if(!checked) {
      checked=true;
      if(!hasFinally()) return 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.tag.TagTry

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.