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