001 package railo.transformer.bytecode.statement.tag; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 007 import org.objectweb.asm.Label; 008 import org.objectweb.asm.Opcodes; 009 import org.objectweb.asm.Type; 010 import org.objectweb.asm.commons.GeneratorAdapter; 011 import org.objectweb.asm.commons.Method; 012 013 import railo.transformer.bytecode.Body; 014 import railo.transformer.bytecode.BodyBase; 015 import railo.transformer.bytecode.BytecodeContext; 016 import railo.transformer.bytecode.BytecodeException; 017 import railo.transformer.bytecode.Position; 018 import railo.transformer.bytecode.Statement; 019 import railo.transformer.bytecode.expression.ExprString; 020 import railo.transformer.bytecode.expression.Expression; 021 import railo.transformer.bytecode.literal.LitString; 022 import railo.transformer.bytecode.statement.FlowControlFinal; 023 import railo.transformer.bytecode.statement.FlowControlFinalImpl; 024 import railo.transformer.bytecode.statement.FlowControlRetry; 025 import railo.transformer.bytecode.statement.TryCatchFinally; 026 import railo.transformer.bytecode.util.ExpressionUtil; 027 import railo.transformer.bytecode.util.Types; 028 import railo.transformer.bytecode.visitor.OnFinally; 029 import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor; 030 031 public final class TagTry extends TagBase implements FlowControlRetry { 032 033 private static final ExprString ANY=LitString.toExprString("any"); 034 035 private static final Method GET_VARIABLE = new Method( 036 "getVariable", 037 Types.OBJECT, 038 new Type[]{Types.STRING}); 039 040 private static final Method TO_PAGE_EXCEPTION = new Method( 041 "toPageException", 042 Types.PAGE_EXCEPTION, 043 new Type[]{Types.THROWABLE}); 044 045 // PageException setCatch(Throwable t) 046 /*private static final Method SET_CATCH_T = new Method( 047 "setCatch", 048 Types.PAGE_EXCEPTION, 049 new Type[]{Types.THROWABLE});*/ 050 051 052 public static final Method SET_CATCH_PE = new Method( 053 "setCatch", 054 Types.VOID, 055 new Type[]{Types.PAGE_EXCEPTION}); 056 057 public static final Method SET_CATCH3 = new Method( 058 "setCatch", 059 Types.VOID, 060 new Type[]{Types.PAGE_EXCEPTION,Types.BOOLEAN_VALUE,Types.BOOLEAN_VALUE}); 061 062 public static final Method GET_CATCH = new Method( 063 "getCatch", 064 Types.PAGE_EXCEPTION, 065 new Type[]{}); 066 067 // public boolean typeEqual(String type); 068 private static final Method TYPE_EQUAL = new Method( 069 "typeEqual", 070 Types.BOOLEAN_VALUE, 071 new Type[]{Types.STRING}); 072 073 private FlowControlFinal fcf; 074 075 private boolean checked; 076 private Label begin = new Label(); 077 078 079 public TagTry(Position start,Position end) { 080 super(start,end); 081 } 082 083 /** 084 * 085 * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter) 086 */ 087 public void _writeOut(BytecodeContext bc) throws BytecodeException { 088 GeneratorAdapter adapter = bc.getAdapter(); 089 adapter.visitLabel(begin); 090 Body tryBody=new BodyBase(); 091 List<Tag> catches=new ArrayList<Tag>(); 092 Tag tmpFinal=null; 093 094 tryBody.setParent(getBody().getParent()); 095 096 List<Statement> statements = getBody().getStatements(); 097 Statement stat; 098 Tag tag; 099 { 100 Iterator<Statement> it = statements.iterator(); 101 while(it.hasNext()) { 102 stat= it.next(); 103 if(stat instanceof Tag) { 104 tag=(Tag) stat; 105 if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Catch")) { 106 catches.add(tag); 107 continue; 108 } 109 else if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Finally")) { 110 tmpFinal=tag; 111 continue; 112 } 113 } 114 tryBody.addStatement(stat); 115 }; 116 } 117 final Tag _finally=tmpFinal; 118 119 // has no try body, if there is no try body, no catches are executed, only finally 120 if(!tryBody.hasStatements()) { 121 122 if(_finally!=null && _finally.getBody()!=null)_finally.getBody().writeOut(bc); 123 return; 124 } 125 TryCatchFinallyVisitor tcfv=new TryCatchFinallyVisitor(new OnFinally() { 126 127 public void writeOut(BytecodeContext bc) throws BytecodeException { 128 /*GeneratorAdapter ga = bc.getAdapter(); 129 if(fcf!=null && fcf.getAfterFinalGOTOLabel()!=null) 130 ASMUtil.visitLabel(ga,fcf.getFinalEntryLabel()); 131 */ 132 if(_finally!=null) { 133 134 ExpressionUtil.visitLine(bc, _finally.getStart()); 135 _finally.getBody().writeOut(bc); 136 137 } 138 /*if(fcf!=null){ 139 Label l=fcf.getAfterFinalGOTOLabel(); 140 if(l!=null)ga.visitJumpInsn(Opcodes.GOTO, l); 141 }*/ 142 } 143 },getFlowControlFinal()); 144 145 146 // Try 147 tcfv.visitTryBegin(bc); 148 tryBody.writeOut(bc); 149 int e=tcfv.visitTryEndCatchBeging(bc); 150 // if(e instanceof railo.runtime.exp.Abort) throw e; 151 Label abortEnd=new Label(); 152 adapter.loadLocal(e); 153 // Abort.isAbort(t); 154 adapter.invokeStatic(Types.ABORT, TryCatchFinally.IS_ABORT); 155 //adapter.instanceOf(Types.ABORT); 156 157 158 159 adapter.ifZCmp(Opcodes.IFEQ, abortEnd); 160 adapter.loadLocal(e); 161 adapter.throwException(); 162 adapter.visitLabel(abortEnd); 163 164 165 // PageExceptionImpl old=pc.getCatch(); 166 int old=adapter.newLocal(Types.PAGE_EXCEPTION); 167 adapter.loadArg(0); 168 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_CATCH); 169 adapter.storeLocal(old); 170 171 // PageException pe=Caster.toPageEception(e); 172 int pe=adapter.newLocal(Types.PAGE_EXCEPTION); 173 adapter.loadLocal(e); 174 adapter.invokeStatic(Types.CASTER, TO_PAGE_EXCEPTION); 175 adapter.storeLocal(pe); 176 177 Iterator<Tag> it = catches.iterator(); 178 Attribute attrType; 179 Expression type; 180 Label endAllIfs=new Label(); 181 Tag tagElse=null; 182 while(it.hasNext()) { 183 tag=it.next(); 184 Label endIf=new Label(); 185 attrType = tag.getAttribute("type"); 186 type=ANY; 187 if(attrType!=null)type=attrType.getValue(); 188 189 if(type instanceof LitString && ((LitString)type).getString().equalsIgnoreCase("any")){ 190 tagElse=tag; 191 continue; 192 } 193 194 ExpressionUtil.visitLine(bc, tag.getStart()); 195 196 // if(pe.typeEqual(@type) 197 adapter.loadLocal(pe); 198 type.writeOut(bc, Expression.MODE_REF); 199 adapter.invokeVirtual(Types.PAGE_EXCEPTION, TYPE_EQUAL); 200 201 adapter.ifZCmp(Opcodes.IFEQ, endIf); 202 catchBody(bc,adapter,tag,pe,true); 203 204 adapter.visitJumpInsn(Opcodes.GOTO, endAllIfs); 205 206 adapter.visitLabel(endIf); 207 208 209 } 210 // else 211 if(tagElse!=null){ 212 catchBody(bc, adapter, tagElse, pe, true); 213 } 214 else{ 215 // pc.setCatch(pe,true); 216 adapter.loadArg(0); 217 adapter.loadLocal(pe); 218 adapter.push(false); 219 adapter.push(true); 220 adapter.invokeVirtual(Types.PAGE_CONTEXT, SET_CATCH3); 221 222 //throw pe; 223 adapter.loadLocal(pe); 224 adapter.throwException(); 225 } 226 adapter.visitLabel(endAllIfs); 227 228 229 // PageExceptionImpl old=pc.getCatch(); 230 adapter.loadArg(0); 231 adapter.loadLocal(old); 232 adapter.invokeVirtual(Types.PAGE_CONTEXT, SET_CATCH_PE); 233 234 tcfv.visitCatchEnd(bc); 235 } 236 237 238 private static void catchBody(BytecodeContext bc, GeneratorAdapter adapter,Tag tag, int pe,boolean caugth) throws BytecodeException { 239 // pc.setCatch(pe,true); 240 adapter.loadArg(0); 241 adapter.loadLocal(pe); 242 adapter.push(caugth); 243 adapter.push(true); 244 adapter.invokeVirtual(Types.PAGE_CONTEXT, SET_CATCH3); 245 tag.getBody().writeOut(bc); 246 247 } 248 249 private boolean hasFinally(){ 250 List<Statement> statements = getBody().getStatements(); 251 Statement stat; 252 Tag tag; 253 Iterator<Statement> it = statements.iterator(); 254 while(it.hasNext()) { 255 stat= it.next(); 256 if(stat instanceof Tag) { 257 tag=(Tag) stat; 258 if(tag.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Finally")) { 259 return true; 260 } 261 } 262 } 263 return false; 264 } 265 266 267 @Override 268 public FlowControlFinal getFlowControlFinal() { 269 if(!checked) { 270 checked=true; 271 if(!hasFinally()) return null; 272 fcf=new FlowControlFinalImpl(); 273 } 274 275 return fcf; 276 } 277 278 @Override 279 public Label getRetryLabel() { 280 return begin; 281 } 282 283 @Override 284 public String getLabel() { 285 return null; 286 } 287 288 289 }