001 package railo.transformer.bytecode.statement.tag; 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 import org.objectweb.asm.commons.Method; 008 009 import railo.commons.io.IOUtil; 010 import railo.commons.io.res.util.ResourceUtil; 011 import railo.runtime.exp.TemplateException; 012 import railo.transformer.bytecode.BytecodeContext; 013 import railo.transformer.bytecode.BytecodeException; 014 import railo.transformer.bytecode.Position; 015 import railo.transformer.bytecode.cast.CastBoolean; 016 import railo.transformer.bytecode.expression.Expression; 017 import railo.transformer.bytecode.statement.FlowControlBreak; 018 import railo.transformer.bytecode.statement.FlowControlContinue; 019 import railo.transformer.bytecode.statement.FlowControlFinal; 020 import railo.transformer.bytecode.statement.ForEach; 021 import railo.transformer.bytecode.util.ASMConstants; 022 import railo.transformer.bytecode.util.ExpressionUtil; 023 import railo.transformer.bytecode.util.Methods; 024 import railo.transformer.bytecode.util.Methods_Caster; 025 import railo.transformer.bytecode.util.Types; 026 import railo.transformer.bytecode.visitor.DecisionDoubleVisitor; 027 import railo.transformer.bytecode.visitor.DecisionIntVisitor; 028 import railo.transformer.bytecode.visitor.DecisionObjectVisitor; 029 import railo.transformer.bytecode.visitor.DoWhileVisitor; 030 import railo.transformer.bytecode.visitor.ForDoubleVisitor; 031 import railo.transformer.bytecode.visitor.ForVisitor; 032 import railo.transformer.bytecode.visitor.LoopVisitor; 033 import railo.transformer.bytecode.visitor.OnFinally; 034 import railo.transformer.bytecode.visitor.TryFinallyVisitor; 035 import railo.transformer.bytecode.visitor.WhileVisitor; 036 037 public final class TagLoop extends TagGroup implements FlowControlBreak,FlowControlContinue { 038 039 040 public static final int TYPE_FILE = 1; 041 public static final int TYPE_LIST = 2; 042 public static final int TYPE_INDEX = 3; 043 public static final int TYPE_CONDITION = 4; 044 public static final int TYPE_QUERY = 5; 045 public static final int TYPE_COLLECTION = 6; 046 public static final int TYPE_ARRAY = 7; 047 public static final int TYPE_GROUP = 8; 048 public static final int TYPE_INNER_GROUP = 9; 049 public static final int TYPE_INNER_QUERY = 10; 050 public static final int TYPE_NOTHING = 11; 051 052 053 054 055 // VariableReference getVariableReference(PageContext pc,String var) 056 private static final Method GET_VARIABLE_REFERENCE = new Method( 057 "getVariableReference", 058 Types.VARIABLE_REFERENCE, 059 new Type[]{Types.PAGE_CONTEXT,Types.STRING}); 060 061 062 // Object set(PageContext pc, Object value) 063 private static final Method SET = new Method( 064 "set", 065 Types.OBJECT, 066 new Type[]{Types.PAGE_CONTEXT,Types.OBJECT}); 067 // Object set(double value) 068 private static final Method SET_DOUBLE = new Method( 069 "set", 070 Types.VOID, 071 new Type[]{Types.DOUBLE_VALUE}); 072 073 074 075 /*private static final Method KEYS = new Method( 076 "keyIterator", 077 Types.COLLECTION_KEY_ARRAY, 078 new Type[]{});*/ 079 080 private static final Method GET = new Method( 081 "get", 082 Types.OBJECT, 083 new Type[]{Types.INT_VALUE,Types.OBJECT}); 084 085 private static final Method NEXT = new Method( 086 "next", 087 Types.OBJECT, 088 new Type[]{}); 089 090 private static final Method HAS_NEXT = new Method( 091 "hasNext", 092 Types.BOOLEAN_VALUE, 093 new Type[]{}); 094 095 // File toFileExisting(PageContext pc ,String destination) 096 private static final Type RESOURCE_UTIL = Type.getType(ResourceUtil.class); 097 private static final Method TO_RESOURCE_EXISTING = new Method( 098 "toResourceExisting", 099 Types.RESOURCE, 100 new Type[]{Types.PAGE_CONTEXT,Types.STRING}); 101 102 // Config getConfig() 103 private static final Method GET_CONFIG = new Method( 104 "getConfig", 105 Types.CONFIG_WEB, 106 new Type[]{}); 107 108 // SecurityManager getSecurityManager() 109 private static final Method GET_SECURITY_MANAGER = new Method( 110 "getSecurityManager", 111 Types.SECURITY_MANAGER, 112 new Type[]{}); 113 114 // void checkFileLocation(File file) 115 private static final Method CHECK_FILE_LOCATION = new Method( 116 "checkFileLocation", 117 Types.VOID, 118 new Type[]{Types.RESOURCE}); 119 120 // Reader getReader(File file, String charset) 121 private static final Type IO_UTIL = Type.getType(IOUtil.class); 122 private static final Method GET_BUFFERED_READER = new Method( 123 "getBufferedReader", 124 Types.BUFFERED_READER, 125 new Type[]{Types.RESOURCE,Types.STRING}); 126 127 // void closeEL(Reader r) 128 private static final Method CLOSE_EL = new Method( 129 "closeEL", 130 Types.VOID, 131 new Type[]{Types.READER}); 132 133 // String readLine() 134 private static final Method READ_LINE = new Method( 135 "readLine", 136 Types.STRING, 137 new Type[]{}); 138 139 140 // Array listToArrayRemoveEmpty(String list, String delimiter) 141 private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SS = new Method( 142 "listToArrayRemoveEmpty", 143 Types.ARRAY, 144 new Type[]{Types.STRING,Types.STRING}); 145 146 // Array listToArrayRemoveEmpty(String list, char delimiter) 147 private static final Method LIST_TO_ARRAY_REMOVE_EMPTY_SC = new Method( 148 "listToArrayRemoveEmpty", 149 Types.ARRAY, 150 new Type[]{Types.STRING,Types.CHAR}); 151 152 private static final Method SIZE = new Method( 153 "size", 154 Types.INT_VALUE, 155 new Type[]{}); 156 157 158 // Object get(int key) klo 159 private static final Method GETE = new Method( 160 "getE", 161 Types.OBJECT, 162 new Type[]{Types.INT_VALUE}); 163 164 165 166 167 // Query getQuery(String key) 168 public static final Method GET_QUERY_OBJ = new Method( 169 "getQuery", 170 Types.QUERY, 171 new Type[]{Types.OBJECT}); 172 public static final Method GET_QUERY_STRING = new Method( 173 "getQuery", 174 Types.QUERY, 175 new Type[]{Types.STRING}); 176 177 // int getCurrentrow() 178 static final Method GET_CURRENTROW_1 = new Method( 179 "getCurrentrow", 180 Types.INT_VALUE, 181 new Type[]{Types.INT_VALUE}); 182 183 static final Method GO = new Method( 184 "go", 185 Types.BOOLEAN_VALUE, 186 new Type[]{Types.INT_VALUE,Types.INT_VALUE}); 187 188 static final Method GET_ID = new Method( 189 "getId", 190 Types.INT_VALUE, 191 new Type[]{}); 192 private static final Method READ = new Method( 193 "read", 194 Types.STRING, 195 new Type[]{Types.READER,Types.INT_VALUE}); 196 private static final Method ENTRY_ITERATOR = new Method("entryIterator",Types.ITERATOR,new Type[]{}); 197 private static final Method GET_KEY = new Method("getKey",Types.OBJECT,new Type[]{}); 198 private static final Method GET_VALUE = new Method("getValue",Types.OBJECT,new Type[]{}); 199 200 201 202 203 204 private int type; 205 private LoopVisitor loopVisitor; 206 private String label; 207 208 public TagLoop(Position start,Position end) { 209 super(start,end); 210 } 211 212 public void setType(int type) { 213 this.type=type; 214 } 215 216 217 /** 218 * 219 * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter) 220 */ 221 public void _writeOut(BytecodeContext bc) throws BytecodeException { 222 boolean old; 223 GeneratorAdapter ga = bc.getAdapter(); 224 225 226 227 switch(type) { 228 case TYPE_COLLECTION: 229 writeOutTypeCollection(bc); 230 break; 231 case TYPE_CONDITION: 232 writeOutTypeCondition(bc); 233 break; 234 case TYPE_FILE: 235 writeOutTypeFile(bc); 236 break; 237 case TYPE_INDEX: 238 writeOutTypeIndex(bc); 239 break; 240 case TYPE_LIST: 241 writeOutTypeListArray(bc,false); 242 break; 243 case TYPE_ARRAY: 244 writeOutTypeListArray(bc,true); 245 break; 246 case TYPE_QUERY: 247 old = bc.changeDoSubFunctions(false); 248 TagGroupUtil.writeOutTypeQuery(this,bc); 249 bc.changeDoSubFunctions(old); 250 //writeOutTypeQuery(bc); 251 break; 252 253 case TYPE_GROUP: 254 old = bc.changeDoSubFunctions(false); 255 TagGroupUtil.writeOutTypeGroup(this,bc); 256 bc.changeDoSubFunctions(old); 257 //writeOutTypeQuery(bc); 258 break; 259 260 case TYPE_INNER_GROUP: 261 old = bc.changeDoSubFunctions(false); 262 TagGroupUtil.writeOutTypeInnerGroup(this,bc); 263 bc.changeDoSubFunctions(old); 264 break; 265 266 case TYPE_INNER_QUERY: 267 old = bc.changeDoSubFunctions(false); 268 TagGroupUtil.writeOutTypeInnerQuery(this,bc); 269 bc.changeDoSubFunctions(old); 270 break; 271 case TYPE_NOTHING: 272 GeneratorAdapter a = bc.getAdapter(); 273 DoWhileVisitor dwv=new DoWhileVisitor(); 274 setLoopVisitor(dwv); 275 dwv.visitBeginBody(a); 276 getBody().writeOut(bc); 277 dwv.visitEndBodyBeginExpr(a); 278 a.push(false); 279 dwv.visitEndExpr(a); 280 281 282 break; 283 284 285 286 default: 287 throw new BytecodeException("invalid type",getStart()); 288 } 289 } 290 291 /** 292 * write out collection loop 293 * @param adapter 294 * @throws TemplateException 295 */ 296 private void writeOutTypeCollection(BytecodeContext bc) throws BytecodeException { 297 298 GeneratorAdapter adapter = bc.getAdapter(); 299 300 //VariableReference item=VariableInterpreter.getVariableReference(pc,index); 301 int index = -1; 302 Attribute attrIndex = getAttribute("index"); 303 if(attrIndex!=null){ 304 index = adapter.newLocal(Types.VARIABLE_REFERENCE); 305 adapter.loadArg(0); 306 attrIndex.getValue().writeOut(bc, Expression.MODE_REF); 307 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 308 adapter.storeLocal(index); 309 } 310 311 //VariableReference item=VariableInterpreter.getVariableReference(pc,item); 312 int item = -1; 313 Attribute attrItem = getAttribute("item"); 314 if(attrItem!=null){ 315 item = adapter.newLocal(Types.VARIABLE_REFERENCE); 316 adapter.loadArg(0); 317 attrItem.getValue().writeOut(bc, Expression.MODE_REF); 318 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 319 adapter.storeLocal(item); 320 } 321 boolean hasIndexAndItem=index!=-1 && item!=-1; 322 323 324 325 WhileVisitor whileVisitor = new WhileVisitor(); 326 loopVisitor=whileVisitor; 327 // java.util.Iterator it=Caster.toIterator(@collection'); 328 int it=adapter.newLocal(Types.ITERATOR); 329 getAttribute("collection").getValue().writeOut(bc,Expression.MODE_REF); 330 331 // item and index 332 int entry=-1; 333 if(hasIndexAndItem) { 334 entry = adapter.newLocal(Types.MAP_ENTRY); 335 // Caster.toCollection(collection) 336 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COLLECTION); 337 //coll.entryIterator(); 338 adapter.invokeInterface(Types.COLLECTION, ENTRY_ITERATOR); 339 } 340 else { 341 adapter.invokeStatic(Types.CASTER,ForEach.TO_ITERATOR); 342 } 343 344 345 adapter.storeLocal(it); 346 347 348 349 350 // while(it.hasNext()) { 351 whileVisitor.visitBeforeExpression(bc); 352 adapter.loadLocal(it); 353 adapter.invokeInterface(Types.ITERATOR, HAS_NEXT); 354 355 whileVisitor.visitAfterExpressionBeforeBody(bc); 356 if(hasIndexAndItem) { 357 // entry=it.next(); 358 adapter.loadLocal(it); 359 adapter.invokeInterface(Types.ITERATOR, NEXT); 360 adapter.storeLocal(entry); 361 362 // keyRef.set(pc,entry.getKey()) 363 adapter.loadLocal(index); 364 adapter.loadArg(0); 365 adapter.loadLocal(entry); 366 adapter.invokeInterface(Types.MAP_ENTRY, GET_KEY); 367 adapter.invokeStatic(Types.CASTER,Methods.METHOD_TO_STRING); 368 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 369 adapter.pop(); 370 371 // valueRef.set(pc,entry.getKey()) 372 adapter.loadLocal(item); 373 adapter.loadArg(0); 374 adapter.loadLocal(entry); 375 adapter.invokeInterface(Types.MAP_ENTRY, GET_VALUE); 376 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 377 adapter.pop(); 378 379 } 380 else { 381 if(index==-1) adapter.loadLocal(item); 382 else adapter.loadLocal(index); 383 384 adapter.loadArg(0); 385 adapter.loadLocal(it); 386 adapter.invokeInterface(Types.ITERATOR, NEXT); 387 388 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 389 adapter.pop(); 390 } 391 392 393 394 395 396 397 getBody().writeOut(bc); 398 whileVisitor.visitAfterBody(bc,getEnd()); 399 400 } 401 402 /** 403 * write out condition loop 404 * @param adapter 405 * @throws TemplateException 406 */ 407 private void writeOutTypeCondition(BytecodeContext bc) throws BytecodeException { 408 WhileVisitor whileVisitor = new WhileVisitor(); 409 loopVisitor=whileVisitor; 410 whileVisitor.visitBeforeExpression(bc); 411 CastBoolean.toExprBoolean(getAttribute("condition").getValue()).writeOut(bc, Expression.MODE_VALUE); 412 whileVisitor.visitAfterExpressionBeforeBody(bc); 413 getBody().writeOut(bc); 414 whileVisitor.visitAfterBody(bc,getEnd()); 415 416 } 417 418 /** 419 * write out file loop 420 * @param adapter 421 * @throws TemplateException 422 */ 423 private void writeOutTypeFile(BytecodeContext bc) throws BytecodeException { 424 WhileVisitor whileVisitor = new WhileVisitor(); 425 loopVisitor=whileVisitor; 426 GeneratorAdapter adapter = bc.getAdapter(); 427 428 // charset=@charset 429 int charset=adapter.newLocal(Types.STRING); 430 Attribute attrCharset = getAttribute("charset"); 431 if(attrCharset==null) adapter.visitInsn(Opcodes.ACONST_NULL); 432 else attrCharset.getValue().writeOut(bc, Expression.MODE_REF); 433 adapter.storeLocal(charset); 434 435 // startline=@startline 436 int startline=adapter.newLocal(Types.INT_VALUE); 437 Attribute attrStartLine = getAttribute("startline"); 438 if(attrStartLine==null) attrStartLine = getAttribute("from"); // CF8 439 if(attrStartLine==null) adapter.push(1); 440 else { 441 attrStartLine.getValue().writeOut(bc, Expression.MODE_VALUE); 442 adapter.visitInsn(Opcodes.D2I); 443 } 444 adapter.storeLocal(startline); 445 446 // endline=@endline 447 int endline=adapter.newLocal(Types.INT_VALUE); 448 Attribute attrEndLine = getAttribute("endline"); 449 if(attrEndLine==null) attrEndLine = getAttribute("to"); 450 if(attrEndLine==null) adapter.push(-1); 451 else { 452 attrEndLine.getValue().writeOut(bc, Expression.MODE_VALUE); 453 adapter.visitInsn(Opcodes.D2I); 454 } 455 adapter.storeLocal(endline); 456 457 458 //VariableReference index=VariableInterpreter.getVariableReference(pc,@index); 459 int index = adapter.newLocal(Types.VARIABLE_REFERENCE); 460 adapter.loadArg(0); 461 462 getAttribute("index").getValue().writeOut(bc, Expression.MODE_REF); 463 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 464 adapter.storeLocal(index); 465 466 //java.io.File file=FileUtil.toResourceExisting(pc,@file); 467 int resource=adapter.newLocal(Types.RESOURCE); 468 adapter.loadArg(0); 469 getAttribute("file").getValue().writeOut(bc, Expression.MODE_REF); 470 adapter.invokeStatic(RESOURCE_UTIL, TO_RESOURCE_EXISTING); 471 adapter.storeLocal(resource); 472 473 // pc.getConfig().getSecurityManager().checkFileLocation(resource); 474 adapter.loadArg(0); 475 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_CONFIG); 476 adapter.invokeInterface(Types.CONFIG_WEB, GET_SECURITY_MANAGER); 477 adapter.loadLocal(resource); 478 adapter.invokeInterface(Types.SECURITY_MANAGER, CHECK_FILE_LOCATION); 479 480 // char[] carr=new char[characters]; 481 Attribute attr = getAttribute("characters"); 482 int carr=-1; 483 if(attr!=null) { 484 carr=adapter.newLocal(Types.CHAR_ARRAY); 485 attr.getValue().writeOut(bc, Expression.MODE_VALUE); 486 adapter.cast(Types.DOUBLE_VALUE, Types.INT_VALUE); 487 adapter.newArray(Types.CHAR); 488 adapter.storeLocal(carr); 489 } 490 491 // BufferedReader reader = IOUtil.getBufferedReader(resource,charset); 492 final int br=adapter.newLocal(Types.BUFFERED_READER); 493 adapter.loadLocal(resource); 494 adapter.loadLocal(charset); 495 adapter.invokeStatic(IO_UTIL, GET_BUFFERED_READER); 496 adapter.storeLocal(br); 497 498 // String line; 499 int line=adapter.newLocal(Types.STRING); 500 501 // int count=0; 502 int count=adapter.newLocal(Types.INT_VALUE); 503 adapter.push(0); 504 adapter.storeLocal(count); 505 506 TryFinallyVisitor tfv=new TryFinallyVisitor(new OnFinally() { 507 public void writeOut(BytecodeContext bc) { 508 bc.getAdapter().loadLocal(br); 509 bc.getAdapter().invokeStatic(IO_UTIL, CLOSE_EL); 510 } 511 },null); 512 //TryFinallyVisitor tcfv=new TryFinallyVisitor(); 513 514 // try 515 tfv.visitTryBegin(bc); 516 //tcfv.visitTryBegin(bc); 517 // while((line=br.readLine())!=null) { 518 //WhileVisitor wv=new WhileVisitor(); 519 whileVisitor.visitBeforeExpression(bc); 520 DecisionObjectVisitor dv=new DecisionObjectVisitor(); 521 dv.visitBegin(); 522 if(attr!=null) { 523 // IOUtil.read(bufferedreader,12) 524 adapter.loadLocal(br); 525 adapter.loadLocal(carr); 526 adapter.arrayLength(); 527 adapter.invokeStatic(Types.IOUTIL, READ); 528 } 529 else { 530 // br.readLine() 531 adapter.loadLocal(br); 532 adapter.invokeVirtual(Types.BUFFERED_READER, READ_LINE); 533 } 534 adapter.dup(); 535 adapter.storeLocal(line); 536 537 dv.visitNEQ(); 538 adapter.visitInsn(Opcodes.ACONST_NULL); 539 dv.visitEnd(bc); 540 541 whileVisitor.visitAfterExpressionBeforeBody(bc); 542 //if(++count < startLine) continue; 543 DecisionIntVisitor dv2=new DecisionIntVisitor(); 544 dv2.visitBegin(); 545 adapter.iinc(count, 1); 546 adapter.loadLocal(count); 547 dv2.visitLT(); 548 adapter.loadLocal(startline); 549 dv2.visitEnd(bc); 550 Label end=new Label(); 551 adapter.ifZCmp(Opcodes.IFEQ, end); 552 whileVisitor.visitContinue(bc); 553 adapter.visitLabel(end); 554 555 // if(endLine!=-1 && count > endLine) break; 556 DecisionIntVisitor div=new DecisionIntVisitor(); 557 div.visitBegin(); 558 adapter.loadLocal(endline); 559 div.visitNEQ(); 560 adapter.push(-1); 561 div.visitEnd(bc); 562 Label end2=new Label(); 563 adapter.ifZCmp(Opcodes.IFEQ, end2); 564 565 DecisionIntVisitor div2 = new DecisionIntVisitor(); 566 div2.visitBegin(); 567 adapter.loadLocal(count); 568 div2.visitGT(); 569 adapter.loadLocal(endline); 570 div2.visitEnd(bc); 571 Label end3=new Label(); 572 adapter.ifZCmp(Opcodes.IFEQ, end3); 573 whileVisitor.visitBreak(bc); 574 adapter.visitLabel(end3); 575 adapter.visitLabel(end2); 576 577 // index.set(pc,line); 578 adapter.loadLocal(index); 579 adapter.loadArg(0); 580 adapter.loadLocal(line); 581 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 582 adapter.pop(); 583 584 getBody().writeOut(bc); 585 586 whileVisitor.visitAfterBody(bc,getEnd()); 587 588 tfv.visitTryEnd(bc); 589 590 } 591 592 /** 593 * write out index loop 594 * @param adapter 595 * @throws TemplateException 596 */ 597 private void writeOutTypeIndex(BytecodeContext bc) throws BytecodeException { 598 ForDoubleVisitor forDoubleVisitor = new ForDoubleVisitor(); 599 loopVisitor=forDoubleVisitor; 600 GeneratorAdapter adapter = bc.getAdapter(); 601 602 // int from=(int)@from; 603 int from=adapter.newLocal(Types.DOUBLE_VALUE); 604 ExpressionUtil.writeOutSilent(getAttribute("from").getValue(), bc, Expression.MODE_VALUE); 605 adapter.storeLocal(from); 606 607 // int to=(int)@to; 608 int to=adapter.newLocal(Types.DOUBLE_VALUE); 609 ExpressionUtil.writeOutSilent(getAttribute("to").getValue(), bc, Expression.MODE_VALUE); 610 adapter.storeLocal(to); 611 612 // int step=(int)@step; 613 int step=adapter.newLocal(Types.DOUBLE_VALUE); 614 Attribute attrStep = getAttribute("step"); 615 if(attrStep!=null) { 616 ExpressionUtil.writeOutSilent(attrStep.getValue(), bc, Expression.MODE_VALUE); 617 } 618 else { 619 adapter.push(1D); 620 } 621 adapter.storeLocal(step); 622 623 // boolean dirPlus=(step > 0); 624 int dirPlus=adapter.newLocal(Types.BOOLEAN_VALUE); 625 DecisionDoubleVisitor div=new DecisionDoubleVisitor(); 626 div.visitBegin(); 627 adapter.loadLocal(step); 628 div.visitGT(); 629 adapter.push(0D); 630 div.visitEnd(bc); 631 adapter.storeLocal(dirPlus); 632 633 //if(step!=0) { 634 div=new DecisionDoubleVisitor(); 635 div.visitBegin(); 636 adapter.loadLocal(step); 637 div.visitNEQ(); 638 adapter.push(0D); 639 div.visitEnd(bc); 640 Label ifEnd=new Label(); 641 adapter.ifZCmp(Opcodes.IFEQ, ifEnd); 642 643 // VariableReference index>=VariableInterpreter.getVariableReference(pc,@index)); 644 int index = adapter.newLocal(Types.VARIABLE_REFERENCE); 645 adapter.loadArg(0); 646 ExpressionUtil.writeOutSilent(getAttribute("index").getValue(), bc, Expression.MODE_REF); 647 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 648 adapter.storeLocal(index); 649 650 651 // index.set(from); 652 adapter.loadLocal(index); 653 adapter.loadLocal(from); 654 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE); 655 656 // for 657 658 //int i=forConditionVisitor.visitBeforeExpression(adapter,from,step,true); 659 660 // init 661 adapter.visitLabel(forDoubleVisitor.beforeInit); 662 forDoubleVisitor.forInit(adapter, from, true); 663 adapter.goTo(forDoubleVisitor.beforeExpr); 664 665 // update 666 adapter.visitLabel(forDoubleVisitor.beforeUpdate); 667 adapter.loadLocal(index); 668 //forConditionVisitor.forUpdate(adapter, step, true); 669 adapter.visitVarInsn(Opcodes.DLOAD, forDoubleVisitor.i); 670 adapter.loadLocal(step); 671 adapter.visitInsn(Opcodes.DADD); 672 adapter.visitInsn(Opcodes.DUP2); 673 adapter.visitVarInsn(Opcodes.DSTORE, forDoubleVisitor.i); 674 675 676 677 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE); 678 679 680 681 682 // expression 683 adapter.visitLabel(forDoubleVisitor.beforeExpr); 684 int i=forDoubleVisitor.i; 685 686 687 688 689 690 adapter.loadLocal(dirPlus); 691 Label l1 = new Label(); 692 adapter.visitJumpInsn(Opcodes.IFEQ, l1); 693 694 div=new DecisionDoubleVisitor(); 695 div.visitBegin(); 696 adapter.visitVarInsn(Opcodes.DLOAD, i); 697 div.visitLTE(); 698 adapter.loadLocal(to); 699 div.visitEnd(bc); 700 701 Label l2 = new Label(); 702 adapter.visitJumpInsn(Opcodes.GOTO, l2); 703 adapter.visitLabel(l1); 704 705 div=new DecisionDoubleVisitor(); 706 div.visitBegin(); 707 adapter.visitVarInsn(Opcodes.DLOAD, i); 708 div.visitGTE(); 709 adapter.loadLocal(to); 710 div.visitEnd(bc); 711 712 adapter.visitLabel(l2); 713 forDoubleVisitor.visitAfterExpressionBeginBody(adapter); 714 715 //adapter.loadLocal(index); 716 //adapter.visitVarInsn(Opcodes.DLOAD, i); 717 //adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE); 718 719 getBody().writeOut(bc); 720 721 forDoubleVisitor.visitEndBody(bc,getEnd()); 722 723 724 725 ////// set i after usage 726 //adapter.loadLocal(index); 727 //adapter.visitVarInsn(Opcodes.DLOAD, i); 728 //adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET_DOUBLE); 729 730 adapter.visitLabel(ifEnd); 731 732 } 733 734 /** 735 * write out list loop 736 * @param adapter 737 * @throws TemplateException 738 */ 739 private void writeOutTypeListArray(BytecodeContext bc, boolean isArray) throws BytecodeException { 740 ForVisitor forVisitor = new ForVisitor(); 741 loopVisitor=forVisitor; 742 GeneratorAdapter adapter = bc.getAdapter(); 743 744 //List.listToArrayRemoveEmpty("", 'c') 745 int array = adapter.newLocal(Types.ARRAY); 746 int len = adapter.newLocal(Types.INT_VALUE); 747 748 if(isArray) { 749 getAttribute("array").getValue().writeOut(bc, Expression.MODE_REF); 750 } 751 else { 752 // array=List.listToArrayRemoveEmpty(list, delimter) 753 getAttribute("list").getValue().writeOut(bc, Expression.MODE_REF); 754 if(containsAttribute("delimiters")) { 755 getAttribute("delimiters").getValue().writeOut(bc, Expression.MODE_REF); 756 adapter.invokeStatic(Types.LIST_UTIL, LIST_TO_ARRAY_REMOVE_EMPTY_SS); 757 } 758 else { 759 adapter.visitIntInsn(Opcodes.BIPUSH, 44);// ',' 760 //adapter.push(','); 761 adapter.invokeStatic(Types.LIST_UTIL, LIST_TO_ARRAY_REMOVE_EMPTY_SC); 762 } 763 } 764 adapter.storeLocal(array); 765 766 767 // int len=array.size(); 768 adapter.loadLocal(array); 769 adapter.invokeInterface(Types.ARRAY, SIZE); 770 adapter.storeLocal(len); 771 772 773 //VariableInterpreter.getVariableReference(pc,Caster.toString(index)); 774 Attribute attrIndex = getAttribute("index"); 775 int index = -1; 776 if(attrIndex!=null) { 777 index = adapter.newLocal(Types.VARIABLE_REFERENCE); 778 adapter.loadArg(0); 779 attrIndex.getValue().writeOut(bc, Expression.MODE_REF); 780 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 781 adapter.storeLocal(index); 782 } 783 784 785 //VariableInterpreter.getVariableReference(pc,Caster.toString(item)); 786 Attribute attrItem = getAttribute("item"); 787 int item = -1; 788 if(attrItem!=null) { 789 item = adapter.newLocal(Types.VARIABLE_REFERENCE); 790 adapter.loadArg(0); 791 attrItem.getValue().writeOut(bc, Expression.MODE_REF); 792 adapter.invokeStatic(Types.VARIABLE_INTERPRETER, GET_VARIABLE_REFERENCE); 793 adapter.storeLocal(item); 794 } 795 796 797 int obj=0; 798 if(isArray)obj=adapter.newLocal(Types.OBJECT); 799 800 // for(int i=1;i<=len;i++) { 801 int i = forVisitor.visitBegin(adapter, 1, false); 802 // index.set(pc, list.get(i)); 803 804 if(isArray) { 805 806 807 // value 808 adapter.loadLocal(array); 809 adapter.visitVarInsn(Opcodes.ILOAD, i); 810 ASMConstants.NULL(adapter); 811 adapter.invokeInterface(Types.ARRAY, GET); 812 adapter.dup(); 813 adapter.storeLocal(obj); 814 Label endIf=new Label(); 815 //adapter.loadLocal(obj); 816 adapter.visitJumpInsn(Opcodes.IFNONNULL, endIf); 817 adapter.goTo(forVisitor.getContinueLabel()); 818 adapter.visitLabel(endIf); 819 820 821 if(item==-1) adapter.loadLocal(index); 822 else adapter.loadLocal(item); 823 824 adapter.loadArg(0); 825 826 827 adapter.loadLocal(obj); 828 829 } 830 else { 831 if(item==-1) adapter.loadLocal(index); 832 else adapter.loadLocal(item); 833 adapter.loadArg(0); 834 adapter.loadLocal(array); 835 adapter.visitVarInsn(Opcodes.ILOAD, i); 836 adapter.invokeInterface(Types.ARRAY, GETE); 837 838 839 } 840 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 841 adapter.pop(); 842 843 844 // key 845 if(index!=-1 && item!=-1) { 846 adapter.loadLocal(index); 847 adapter.loadArg(0); 848 adapter.visitVarInsn(Opcodes.ILOAD, i); 849 adapter.cast(Types.INT_VALUE,Types.DOUBLE_VALUE); 850 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DOUBLE[Methods_Caster.DOUBLE]); 851 adapter.invokeVirtual(Types.VARIABLE_REFERENCE, SET); 852 adapter.pop(); 853 } 854 855 856 getBody().writeOut(bc); 857 forVisitor.visitEnd(bc, len, true,getStart()); 858 } 859 860 /* * 861 * write out query loop 862 * @param adapter 863 * @throws TemplateException 864 * / 865 private void writeOutTypeQuery(BytecodeContext bc) throws BytecodeException { 866 ForConditionIntVisitor forConditionVisitor = new ForConditionIntVisitor();// TODO replace with ForIntVisitor 867 loopVisitor=forConditionVisitor; 868 final GeneratorAdapter adapter = bc.getAdapter(); 869 870 // railo.runtime.type.Query query=pc.getQuery(@query); 871 final int query=adapter.newLocal(Types.QUERY); 872 adapter.loadArg(0); 873 Expression val = getAttribute("query").getValue(); 874 val.writeOut(bc, Expression.MODE_REF); 875 if(val instanceof LitString) 876 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_QUERY_STRING); 877 else 878 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_QUERY_OBJ); 879 //adapter.dup(); 880 adapter.storeLocal(query); 881 882 //int queryImpl = adapter.newLocal(Types.QUERY_IMPL); 883 //adapter.checkCast(Types.QUERY_IMPL); 884 //adapter.storeLocal(queryImpl); 885 886 887 // int startAt=query.getCurrentrow(); 888 final int startAt=adapter.newLocal(Types.INT_VALUE); 889 890 adapter.loadLocal(query); 891 adapter.loadArg(0); 892 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 893 adapter.invokeInterface(Types.QUERY, GET_CURRENTROW_1); 894 adapter.storeLocal(startAt); 895 896 897 // startrow 898 int start=adapter.newLocal(Types.INT_VALUE); 899 Attribute attrStartRow = getAttribute("startrow"); 900 if(attrStartRow!=null){ 901 //railo.runtime.util.NumberRange.range(@startrow,1) 902 attrStartRow.getValue().writeOut(bc, Expression.MODE_VALUE); 903 adapter.push(1d); 904 adapter.invokeStatic(Types.NUMBER_RANGE, RANGE); 905 adapter.visitInsn(Opcodes.D2I); 906 } 907 else { 908 adapter.push(1); 909 } 910 adapter.storeLocal(start); 911 912 // endrow 913 int end=adapter.newLocal(Types.INT_VALUE); 914 Attribute attrEndRow = getAttribute("endrow"); 915 if(attrEndRow!=null){ 916 attrEndRow.getValue().writeOut(bc, Expression.MODE_VALUE); 917 adapter.visitInsn(Opcodes.D2I); 918 adapter.storeLocal(end); 919 } 920 921 // pc.us().addQuery(query); 922 adapter.loadArg(0); 923 adapter.invokeVirtual(Types.PAGE_CONTEXT, US); 924 adapter.loadLocal(query); 925 adapter.invokeInterface(UNDEFINED, ADD_QUERY); 926 927 // try 928 TryFinallyVisitor tfv=new TryFinallyVisitor(new OnFinally() { 929 public void writeOut(BytecodeContext bc) { 930 //GeneratorAdapter ga = bc.getAdapter(); 931 // pc.us().removeCollection(); 932 adapter.loadArg(0); 933 adapter.invokeVirtual(Types.PAGE_CONTEXT, US); 934 adapter.invokeInterface(UNDEFINED, REMOVE_QUERY); 935 936 // query.go(startAt); 937 adapter.loadLocal(query); 938 adapter.loadLocal(startAt); 939 940 adapter.loadArg(0); 941 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 942 adapter.invokeInterface(Types.QUERY, GO); 943 adapter.pop(); 944 } 945 }); 946 tfv.visitTryBegin(bc); 947 // For 948 949 int i=forConditionVisitor.visitBegin(adapter, start, true); 950 getBody().writeOut(bc); 951 forConditionVisitor.visitEndBeforeCondition(bc,1,false,getStart()); 952 953 // && i<=endrow 954 if(attrEndRow!=null){ 955 AndVisitor av=new AndVisitor(); 956 av.visitBegin(); 957 adapter.loadLocal(query); 958 adapter.visitVarInsn(Opcodes.ILOAD, i); 959 960 adapter.loadArg(0); 961 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 962 adapter.invokeInterface(Types.QUERY, GO); 963 964 av.visitMiddle(bc); 965 //LitBoolean.TRUE.writeOut(bc, Expression.MODE_VALUE); 966 DecisionIntVisitor dv=new DecisionIntVisitor(); 967 dv.visitBegin(); 968 adapter.visitVarInsn(Opcodes.ILOAD, i); 969 dv.visitLTE(); 970 adapter.loadLocal(end); 971 dv.visitEnd(bc); 972 av.visitEnd(bc); 973 } 974 else { 975 adapter.loadLocal(query); 976 adapter.visitVarInsn(Opcodes.ILOAD, i); 977 978 adapter.loadArg(0); 979 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 980 adapter.invokeInterface(Types.QUERY, GO); 981 982 983 } 984 985 986 forConditionVisitor.visitEndAfterCondition(bc); 987 988 // Finally 989 tfv.visitTryEnd(bc); 990 }*/ 991 992 /** 993 * @see railo.transformer.bytecode.statement.FlowControl#getBreakLabel() 994 */ 995 public Label getBreakLabel() { 996 return loopVisitor.getBreakLabel(); 997 } 998 999 /** 1000 * @see railo.transformer.bytecode.statement.FlowControl#getContinueLabel() 1001 */ 1002 public Label getContinueLabel() { 1003 return loopVisitor.getContinueLabel(); 1004 } 1005 1006 @Override 1007 public short getType() { 1008 return TAG_LOOP; 1009 } 1010 1011 public void setLoopVisitor(LoopVisitor loopVisitor) { 1012 this.loopVisitor=loopVisitor; 1013 } 1014 1015 @Override 1016 public FlowControlFinal getFlowControlFinal() { 1017 return null; 1018 } 1019 1020 public void setLabel(String label) { 1021 this.label=label; 1022 } 1023 1024 @Override 1025 public String getLabel() { 1026 return label; 1027 } 1028 }