001 package railo.transformer.bytecode; 002 003 import java.io.IOException; 004 import java.util.ArrayList; 005 import java.util.Iterator; 006 import java.util.List; 007 import java.util.Map; 008 import java.util.Map.Entry; 009 010 import org.objectweb.asm.ClassAdapter; 011 import org.objectweb.asm.ClassReader; 012 import org.objectweb.asm.ClassWriter; 013 import org.objectweb.asm.FieldVisitor; 014 import org.objectweb.asm.Label; 015 import org.objectweb.asm.MethodVisitor; 016 import org.objectweb.asm.Opcodes; 017 import org.objectweb.asm.Type; 018 import org.objectweb.asm.commons.GeneratorAdapter; 019 import org.objectweb.asm.commons.Method; 020 021 import railo.commons.io.res.Resource; 022 import railo.commons.lang.NumberUtil; 023 import railo.commons.lang.StringUtil; 024 import railo.runtime.component.ImportDefintion; 025 import railo.runtime.exp.TemplateException; 026 import railo.runtime.type.KeyImpl; 027 import railo.runtime.type.StructImpl; 028 import railo.runtime.type.UDF; 029 import railo.runtime.type.scope.Undefined; 030 import railo.runtime.type.util.KeyConstants; 031 import railo.transformer.bytecode.expression.Expression; 032 import railo.transformer.bytecode.extern.StringExternalizerWriter; 033 import railo.transformer.bytecode.literal.LitString; 034 import railo.transformer.bytecode.statement.Argument; 035 import railo.transformer.bytecode.statement.Function; 036 import railo.transformer.bytecode.statement.HasBodies; 037 import railo.transformer.bytecode.statement.HasBody; 038 import railo.transformer.bytecode.statement.IFunction; 039 import railo.transformer.bytecode.statement.NativeSwitch; 040 import railo.transformer.bytecode.statement.tag.Attribute; 041 import railo.transformer.bytecode.statement.tag.Tag; 042 import railo.transformer.bytecode.statement.tag.TagImport; 043 import railo.transformer.bytecode.statement.tag.TagThread; 044 import railo.transformer.bytecode.util.ASMConstants; 045 import railo.transformer.bytecode.util.ASMUtil; 046 import railo.transformer.bytecode.util.ExpressionUtil; 047 import railo.transformer.bytecode.util.Types; 048 import railo.transformer.bytecode.visitor.ArrayVisitor; 049 import railo.transformer.bytecode.visitor.ConditionVisitor; 050 import railo.transformer.bytecode.visitor.DecisionIntVisitor; 051 import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor; 052 053 /** 054 * represent a single Page like "index.cfm" 055 */ 056 public final class Page extends BodyBase { 057 058 059 public void doFinalize(BytecodeContext bc) { 060 ExpressionUtil.visitLine(bc, getEndLine()+1); 061 } 062 063 private static final Type KEY_IMPL = Type.getType(KeyImpl.class); 064 private static final Type KEY_CONSTANTS = Type.getType(KeyConstants.class); 065 private static final Method KEY_INIT = new Method( 066 "init", 067 Types.COLLECTION_KEY, 068 new Type[]{Types.STRING} 069 ); 070 private static final Method KEY_INTERN = new Method( 071 "intern", 072 Types.COLLECTION_KEY, 073 new Type[]{Types.STRING} 074 ); 075 076 // public static ImportDefintion getInstance(String fullname,ImportDefintion defaultValue) 077 private static final Method ID_GET_INSTANCE = new Method( 078 "getInstance", 079 Types.IMPORT_DEFINITIONS, 080 new Type[]{Types.STRING,Types.IMPORT_DEFINITIONS} 081 ); 082 083 public final static Method STATIC_CONSTRUCTOR = Method.getMethod("void <clinit> ()V"); 084 //public final static Method CONSTRUCTOR = Method.getMethod("void <init> ()V"); 085 086 private static final Method CONSTRUCTOR = new Method( 087 "<init>", 088 Types.VOID, 089 new Type[]{}// 090 ); 091 private static final Method CONSTRUCTOR_PS = new Method( 092 "<init>", 093 Types.VOID, 094 new Type[]{Types.PAGE_SOURCE}// 095 ); 096 097 public static final Type STRUCT_IMPL = Type.getType(StructImpl.class); 098 private static final Method INIT_STRUCT_IMPL = new Method( 099 "<init>", 100 Types.VOID, 101 new Type[]{} 102 ); 103 104 105 // void call (railo.runtime.PageContext) 106 private final static Method CALL = new Method( 107 "call", 108 Types.VOID, 109 new Type[]{Types.PAGE_CONTEXT} 110 ); 111 112 /*/ void _try () 113 private final static Method TRY = new Method( 114 "_try", 115 Types.VOID, 116 new Type[]{} 117 );*/ 118 119 // int getVersion() 120 private final static Method VERSION = new Method( 121 "getVersion", 122 Types.INT_VALUE, 123 new Type[]{} 124 ); 125 126 private final static Method SET_PAGE_SOURCE = new Method( 127 "setPageSource", 128 Types.VOID, 129 new Type[]{Types.PAGE_SOURCE} 130 ); 131 132 // public ImportDefintion[] getImportDefintions() 133 private final static Method GET_IMPORT_DEFINITIONS = new Method( 134 "getImportDefintions", 135 Types.IMPORT_DEFINITIONS_ARRAY, 136 new Type[]{} 137 ); 138 139 // long getSourceLastModified() 140 private final static Method LAST_MOD = new Method( 141 "getSourceLastModified", 142 Types.LONG_VALUE, 143 new Type[]{} 144 ); 145 146 private final static Method COMPILE_TIME = new Method( 147 "getCompileTime", 148 Types.LONG_VALUE, 149 new Type[]{} 150 ); 151 152 private static final Type USER_DEFINED_FUNCTION = Type.getType(UDF.class); 153 private static final Method UDF_CALL = new Method( 154 "udfCall", 155 Types.OBJECT, 156 new Type[]{Types.PAGE_CONTEXT, USER_DEFINED_FUNCTION, Types.INT_VALUE} 157 ); 158 159 160 private static final Method THREAD_CALL = new Method( 161 "threadCall", 162 Types.VOID, 163 new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE} 164 ); 165 166 private static final Method UDF_DEFAULT_VALUE = new Method( 167 "udfDefaultValue", 168 Types.OBJECT, 169 new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE, Types.INT_VALUE} 170 ); 171 172 private static final Method NEW_COMPONENT_IMPL_INSTANCE = new Method( 173 "newInstance", 174 Types.COMPONENT_IMPL, 175 new Type[]{Types.PAGE_CONTEXT,Types.STRING,Types.BOOLEAN_VALUE} 176 ); 177 178 private static final Method NEW_INTERFACE_IMPL_INSTANCE = new Method( 179 "newInstance", 180 Types.INTERFACE_IMPL, 181 new Type[]{Types.STRING,Types.BOOLEAN_VALUE,Types.MAP} 182 ); 183 184 185 186 187 188 // void init(PageContext pc,Component Impl c) throws PageException 189 private static final Method INIT_COMPONENT = new Method( 190 "initComponent", 191 Types.VOID, 192 new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_IMPL} 193 ); 194 private static final Method INIT_INTERFACE = new Method( 195 "initInterface", 196 Types.VOID, 197 new Type[]{Types.INTERFACE_IMPL} 198 ); 199 200 201 // public boolean setMode(int mode) { 202 private static final Method SET_MODE = new Method( 203 "setMode", 204 Types.INT_VALUE, 205 new Type[]{Types.INT_VALUE} 206 ); 207 208 209 210 211 212 213 214 215 private static final Method CONSTR_INTERFACE_IMPL = new Method( 216 "<init>", 217 Types.VOID, 218 new Type[]{ 219 Types.INTERFACE_PAGE, 220 Types.STRING, // extends 221 Types.STRING, // hind 222 Types.STRING, // display 223 Types.STRING, // callpath 224 Types.BOOLEAN_VALUE, // realpath 225 Types.MAP, //interfaceudfs 226 Types.MAP // meta 227 } 228 ); 229 230 231 //void init(PageContext pageContext,ComponentPage componentPage) 232 private static final Method INIT = new Method( 233 "init", 234 Types.VOID, 235 new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE} 236 ); 237 238 private static final Method CHECK_INTERFACE = new Method( 239 "checkInterface", 240 Types.VOID, 241 new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE} 242 ); 243 244 245 246 // boolean getOutput() 247 private static final Method GET_OUTPUT = new Method( 248 "getOutput", 249 Types.BOOLEAN_VALUE, 250 new Type[]{} 251 ); 252 253 254 private static final Method PUSH_BODY = new Method( 255 "pushBody", 256 Types.BODY_CONTENT, 257 new Type[]{} 258 ); 259 260 /*/ boolean setSilent() 261 private static final Method SET_SILENT = new Method( 262 "setSilent", 263 Types.BOOLEAN_VALUE, 264 new Type[]{} 265 ); 266 */ 267 // Scope beforeCall(PageContext pc) 268 private static final Method BEFORE_CALL = new Method( 269 "beforeCall", 270 Types.VARIABLES, 271 new Type[]{Types.PAGE_CONTEXT} 272 ); 273 274 private static final Method TO_PAGE_EXCEPTION = new Method( 275 "toPageException", 276 Types.PAGE_EXCEPTION, 277 new Type[]{Types.THROWABLE}); 278 279 280 // boolean unsetSilent() 281 /*private static final Method UNSET_SILENT = new Method( 282 "unsetSilent", 283 Types.BOOLEAN_VALUE, 284 new Type[]{} 285 );*/ 286 287 // void afterCall(PageContext pc, Scope parent) 288 private static final Method AFTER_CALL = new Method( 289 "afterConstructor", 290 Types.VOID, 291 new Type[]{Types.PAGE_CONTEXT,Types.VARIABLES} 292 ); 293 294 // ComponentImpl(ComponentPage,boolean, String, String, String) NS==No Style 295 296 297 // Component Impl(ComponentPage,boolean, String, String, String, String) WS==With Style 298 private static final Method CONSTR_COMPONENT_IMPL = new Method( 299 "<init>", 300 Types.VOID, 301 new Type[]{ 302 Types.COMPONENT_PAGE, 303 Types.BOOLEAN, 304 Types.BOOLEAN_VALUE, 305 Types.STRING, 306 Types.STRING, 307 Types.STRING, 308 Types.STRING, 309 Types.STRING, 310 Types.BOOLEAN_VALUE, 311 Types.STRING, 312 Types.BOOLEAN_VALUE, 313 Types.BOOLEAN_VALUE, 314 STRUCT_IMPL 315 } 316 ); 317 private static final Method SET_EL = new Method( 318 "setEL", 319 Types.OBJECT, 320 new Type[]{Types.STRING,Types.OBJECT} 321 ); 322 private static final Method UNDEFINED_SCOPE = new Method( 323 "us", 324 Types.UNDEFINED, 325 new Type[]{} 326 ); 327 private static final Method FLUSH_AND_POP = new Method( 328 "flushAndPop", 329 Types.VOID, 330 new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT} 331 ); 332 private static final Method CLEAR_AND_POP = new Method( 333 "clearAndPop", 334 Types.VOID, 335 new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT} 336 ); 337 public static final byte CF = (byte)207; 338 public static final byte _33 = (byte)51; 339 private static final boolean ADD_C33 = false; 340 //private static final String SUB_CALL_UDF = "udfCall"; 341 private static final String SUB_CALL_UDF = "_"; 342 343 private int version; 344 private long lastModifed; 345 private String name; 346 347 //private Body body=new Body(); 348 private Resource source; 349 private final String path; 350 private boolean isComponent; 351 private boolean isInterface; 352 353 private List functions=new ArrayList(); 354 private List threads=new ArrayList(); 355 private boolean _writeLog; 356 private StringExternalizerWriter externalizer; 357 358 359 360 public Page(Resource source,String name,int version, long lastModifed, boolean writeLog) { 361 name=name.replace('.', '/'); 362 //body.setParent(this); 363 this.name=name; 364 this.version=version; 365 this.lastModifed=lastModifed; 366 this.source=source; 367 this.path=source.getAbsolutePath(); 368 369 this._writeLog=writeLog; 370 } 371 372 /** 373 * result byte code as binary array 374 * @param classFile 375 * @return byte code 376 * @throws IOException 377 * @throws TemplateException 378 */ 379 public byte[] execute(Resource classFile) throws BytecodeException { 380 381 try { 382 Resource p = classFile.getParentResource().getRealResource(classFile.getName()+".txt"); 383 this.externalizer=new StringExternalizerWriter(p); 384 } catch (IOException e) {} 385 386 List keys=new ArrayList(); 387 ClassWriter cw = ASMUtil.getClassWriter(); 388 //ClassWriter cw = new ClassWriter(true); 389 390 ArrayList<String> list = new ArrayList<String>(); 391 getImports(list, this); 392 393 // parent 394 String parent="railo/runtime/PagePlus";// FUTURE use Page instead of PagePlus 395 if(isComponent()) parent="railo/runtime/ComponentPage"; 396 else if(isInterface()) parent="railo/runtime/InterfacePage"; 397 398 cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL, name, null, parent, null); 399 cw.visitSource(this.path, null); 400 401 // static constructor 402 GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,STATIC_CONSTRUCTOR,null,null,cw); 403 BytecodeContext statConstr = new BytecodeContext(null,null,externalizer,keys,cw,name,ga,STATIC_CONSTRUCTOR,writeLog()); 404 405 // private static ImportDefintion[] test=new ImportDefintion[]{...}; 406 if(list.size()>0){ 407 FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC, 408 "imports", "[Lrailo/runtime/component/ImportDefintion;", null, null); 409 fv.visitEnd(); 410 411 GeneratorAdapter adapter = statConstr.getAdapter(); 412 ArrayVisitor av=new ArrayVisitor(); 413 av.visitBegin(adapter,Types.IMPORT_DEFINITIONS,list.size()); 414 int index=0; 415 Iterator<String> it = list.iterator(); 416 while(it.hasNext()){ 417 av.visitBeginItem(adapter,index++); 418 adapter.push(it.next()); 419 ASMConstants.NULL(adapter); 420 adapter.invokeStatic(Types.IMPORT_DEFINITIONS, ID_GET_INSTANCE); 421 av.visitEndItem(adapter); 422 } 423 av.visitEnd(); 424 adapter.visitFieldInsn(Opcodes.PUTSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;"); 425 426 } 427 428 429 // constructor 430 ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR_PS,null,null,cw); 431 BytecodeContext constr = new BytecodeContext(null,null,externalizer,keys,cw,name,ga,CONSTRUCTOR_PS,writeLog()); 432 ga.loadThis(); 433 Type t=Types.PAGE_PLUS; 434 if(isComponent())t=Types.COMPONENT_PAGE; 435 else if(isInterface())t=Types.INTERFACE_PAGE; 436 437 ga.invokeConstructor(t, CONSTRUCTOR); 438 439 440 //setPageSource(pageSource); 441 ga.visitVarInsn(Opcodes.ALOAD, 0); 442 ga.visitVarInsn(Opcodes.ALOAD, 1); 443 ga.invokeVirtual(t, SET_PAGE_SOURCE); 444 // mv.visitMethodInsn(INVOKEVIRTUAL, "railo/runtime/PagePlus", "setPageSource", "(Lrailo/runtime/PageSource;)V"); 445 446 447 448 449 450 451 // getVersion 452 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , VERSION, null, null, cw); 453 adapter.push(version); 454 adapter.returnValue(); 455 adapter.endMethod(); 456 457 458 // public ImportDefintion[] getImportDefintions() 459 if(list.size()>0){ 460 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , GET_IMPORT_DEFINITIONS, null, null, cw); 461 adapter.visitFieldInsn(Opcodes.GETSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;"); 462 adapter.returnValue(); 463 adapter.endMethod(); 464 } 465 466 467 468 // getSourceLastModified 469 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , LAST_MOD, null, null, cw); 470 adapter.push(lastModifed); 471 adapter.returnValue(); 472 adapter.endMethod(); 473 474 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , COMPILE_TIME, null, null, cw); 475 adapter.push(System.currentTimeMillis()); 476 adapter.returnValue(); 477 adapter.endMethod(); 478 479 // newInstance/initComponent/call 480 if(isComponent()) { 481 Tag component=getComponent(); 482 writeOutNewComponent(statConstr,constr,keys,cw,component); 483 writeOutInitComponent(statConstr,constr,keys,cw,component); 484 } 485 else if(isInterface()) { 486 Tag interf=getInterface(); 487 writeOutNewInterface(statConstr,constr,keys,cw,interf); 488 writeOutInitInterface(statConstr,constr,keys,cw,interf); 489 } 490 else { 491 writeOutCall(statConstr,constr,keys,cw); 492 } 493 494 // udfCall 495 Function[] functions=getFunctions(); 496 497 ConditionVisitor cv; 498 DecisionIntVisitor div; 499 // less/equal than 10 functions 500 if(functions.length==0 || isInterface()){} 501 else if(functions.length<=10) { 502 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw); 503 BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog()); 504 if(functions.length==0){} 505 else if(functions.length==1){ 506 ExpressionUtil.visitLine(bc,functions[0].getStartLine()); 507 functions[0].getBody().writeOut(bc); 508 ExpressionUtil.visitLine(bc,functions[0].getEndLine()); 509 } 510 else writeOutUdfCallInner(bc,functions,0,functions.length); 511 adapter.visitInsn(Opcodes.ACONST_NULL); 512 adapter.returnValue(); 513 adapter.endMethod(); 514 } 515 // more than 10 functions 516 else { 517 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw); 518 BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog()); 519 cv = new ConditionVisitor(); 520 cv.visitBefore(); 521 int count=0; 522 for(int i=0;i<functions.length;i+=10) { 523 cv.visitWhenBeforeExpr(); 524 div=new DecisionIntVisitor(); 525 div.visitBegin(); 526 adapter.loadArg(2); 527 div.visitLT(); 528 adapter.push(i+10); 529 div.visitEnd(bc); 530 cv.visitWhenAfterExprBeforeBody(bc); 531 532 adapter.visitVarInsn(Opcodes.ALOAD, 0); 533 adapter.visitVarInsn(Opcodes.ALOAD, 1); 534 adapter.visitVarInsn(Opcodes.ALOAD, 2); 535 adapter.visitVarInsn(Opcodes.ILOAD, 3); 536 adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, name, createFunctionName(++count), "(Lrailo/runtime/PageContext;Lrailo/runtime/type/UDF;I)Ljava/lang/Object;"); 537 adapter.visitInsn(Opcodes.ARETURN);//adapter.returnValue(); 538 cv.visitWhenAfterBody(bc); 539 } 540 cv.visitAfter(bc); 541 542 adapter.visitInsn(Opcodes.ACONST_NULL); 543 adapter.returnValue(); 544 adapter.endMethod(); 545 546 count=0; 547 Method innerCall; 548 for(int i=0;i<functions.length;i+=10) { 549 innerCall = new Method(createFunctionName(++count),Types.OBJECT,new Type[]{Types.PAGE_CONTEXT, USER_DEFINED_FUNCTION, Types.INT_VALUE}); 550 551 adapter = new GeneratorAdapter(Opcodes.ACC_PRIVATE+Opcodes.ACC_FINAL , innerCall, null, new Type[]{Types.THROWABLE}, cw); 552 writeOutUdfCallInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,innerCall,writeLog()), functions, i, i+10>functions.length?functions.length:i+10); 553 554 adapter.visitInsn(Opcodes.ACONST_NULL); 555 adapter.returnValue(); 556 adapter.endMethod(); 557 } 558 } 559 560 561 // threadCall 562 TagThread[] threads=getThreads(); 563 if(threads.length>0) { 564 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , THREAD_CALL, null, new Type[]{Types.THROWABLE}, cw); 565 writeOutThreadCallInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,THREAD_CALL,writeLog()),threads,0,threads.length); 566 //adapter.visitInsn(Opcodes.ACONST_NULL); 567 adapter.returnValue(); 568 adapter.endMethod(); 569 } 570 571 572 573 574 // udfDefaultValue 575 // less/equal than 10 functions 576 if(functions.length==0 || isInterface()) {} 577 else if(functions.length<=10) { 578 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 579 writeUdfDefaultValueInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog()),functions,0,functions.length); 580 581 ASMConstants.NULL(adapter); 582 adapter.returnValue(); 583 adapter.endMethod(); 584 } 585 else { 586 adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 587 BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog()); 588 cv = new ConditionVisitor(); 589 cv.visitBefore(); 590 int count=0; 591 for(int i=0;i<functions.length;i+=10) { 592 cv.visitWhenBeforeExpr(); 593 div=new DecisionIntVisitor(); 594 div.visitBegin(); 595 adapter.loadArg(1); 596 div.visitLT(); 597 adapter.push(i+10); 598 div.visitEnd(bc); 599 cv.visitWhenAfterExprBeforeBody(bc); 600 601 adapter.visitVarInsn(Opcodes.ALOAD, 0); 602 adapter.visitVarInsn(Opcodes.ALOAD, 1); 603 adapter.visitVarInsn(Opcodes.ILOAD, 2); 604 adapter.visitVarInsn(Opcodes.ILOAD, 3); 605 adapter.visitMethodInsn(Opcodes.INVOKEVIRTUAL, name, "udfDefaultValue"+(++count), "(Lrailo/runtime/PageContext;II)Ljava/lang/Object;"); 606 adapter.visitInsn(Opcodes.ARETURN);//adapter.returnValue(); 607 608 cv.visitWhenAfterBody(bc); 609 } 610 cv.visitAfter(bc); 611 612 adapter.visitInsn(Opcodes.ACONST_NULL); 613 adapter.returnValue(); 614 adapter.endMethod(); 615 616 count=0; 617 Method innerDefaultValue; 618 for(int i=0;i<functions.length;i+=10) { 619 innerDefaultValue = new Method("udfDefaultValue"+(++count),Types.OBJECT,new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE, Types.INT_VALUE}); 620 adapter = new GeneratorAdapter(Opcodes.ACC_PRIVATE+Opcodes.ACC_FINAL , innerDefaultValue, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 621 writeUdfDefaultValueInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,innerDefaultValue,writeLog()), functions, i, i+10>functions.length?functions.length:i+10); 622 623 adapter.visitInsn(Opcodes.ACONST_NULL); 624 adapter.returnValue(); 625 adapter.endMethod(); 626 } 627 628 } 629 630 631 registerFields(statConstr,keys); 632 633 634 635 statConstr.getAdapter().returnValue(); 636 statConstr.getAdapter().endMethod(); 637 638 639 adapter = constr.getAdapter();//new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR,null,null,cw); 640 641 adapter.returnValue(); 642 adapter.endMethod(); 643 644 try { 645 if(externalizer!=null)externalizer.writeOut(); 646 } catch (IOException e) { 647 throw new BytecodeException(e.getMessage(), -1); 648 } 649 650 651 if(ADD_C33) { 652 byte[] tmp = cw.toByteArray(); 653 byte[] bLastMod=NumberUtil.longToByteArray(lastModifed); 654 byte[] barr = new byte[tmp.length+10]; 655 // Magic Number 656 barr[0]=CF; // CF 657 barr[1]=_33; // 33 658 659 // Last Modified 660 for(int i=0;i<8;i++){ 661 barr[i+2]=bLastMod[i]; 662 } 663 for(int i=0;i<tmp.length;i++){ 664 barr[i+10]=tmp[i]; 665 } 666 return barr; 667 } 668 return cw.toByteArray(); 669 670 } 671 672 673 674 675 private String createFunctionName(int i) { 676 return "_"+Integer.toString(i, Character.MAX_RADIX); 677 } 678 679 private boolean writeLog() { 680 return _writeLog && !isInterface(); 681 } 682 683 public static void registerFields(BytecodeContext bc, List keys) throws BytecodeException { 684 //if(keys.size()==0) return; 685 686 GeneratorAdapter ga = bc.getAdapter(); 687 688 FieldVisitor fv = bc.getClassWriter().visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_STATIC, 689 "keys", Types.COLLECTION_KEY_ARRAY.toString(), null, null); 690 fv.visitEnd(); 691 692 693 int index=0; 694 LitString value; 695 Iterator it = keys.iterator(); 696 //ga.visitVarInsn(Opcodes.ALOAD, 0); 697 ga.push(keys.size()); 698 ga.newArray(Types.COLLECTION_KEY); 699 while(it.hasNext()) { 700 value=(LitString) it.next(); 701 ga.dup(); 702 ga.push(index++); 703 704 /*String str = value.getString(); 705 if(KeyConstants.hasConstant(str)) { 706 ga.getStatic(KEY_CONSTANTS, "_"+str, Types.COLLECTION_KEY); 707 } 708 else {*/ 709 ExpressionUtil.writeOutSilent(value,bc, Expression.MODE_REF); 710 ga.invokeStatic(KEY_IMPL, KEY_INTERN); 711 //} 712 ga.visitInsn(Opcodes.AASTORE); 713 } 714 ga.visitFieldInsn(Opcodes.PUTSTATIC, 715 bc.getClassName(), "keys", Types.COLLECTION_KEY_ARRAY.toString()); 716 717 //statcConst.returnValue(); 718 //statcConst.endMethod(); 719 720 } 721 722 private void writeUdfDefaultValueInner(BytecodeContext bc, Function[] functions, int offset, int length) throws BytecodeException { 723 GeneratorAdapter adapter = bc.getAdapter(); 724 ConditionVisitor cv = new ConditionVisitor(); 725 DecisionIntVisitor div; 726 cv.visitBefore(); 727 for(int i=offset;i<length;i++) { 728 cv.visitWhenBeforeExpr(); 729 div = new DecisionIntVisitor(); 730 div.visitBegin(); 731 adapter.loadArg(1); 732 div.visitEQ(); 733 adapter.push(i); 734 div.visitEnd(bc); 735 cv.visitWhenAfterExprBeforeBody(bc); 736 writeOutFunctionDefaultValueInnerInner(bc, functions[i]); 737 cv.visitWhenAfterBody(bc); 738 } 739 cv.visitAfter(bc); 740 } 741 742 743 private void writeOutUdfCallInnerIf(BytecodeContext bc,Function[] functions, int offset, int length) throws BytecodeException { 744 GeneratorAdapter adapter = bc.getAdapter(); 745 ConditionVisitor cv=new ConditionVisitor(); 746 DecisionIntVisitor div; 747 cv.visitBefore(); 748 for(int i=offset;i<length;i++) { 749 cv.visitWhenBeforeExpr(); 750 div=new DecisionIntVisitor(); 751 div.visitBegin(); 752 adapter.loadArg(2); 753 div.visitEQ(); 754 adapter.push(i); 755 div.visitEnd(bc); 756 cv.visitWhenAfterExprBeforeBody(bc); 757 ExpressionUtil.visitLine(bc, functions[i].getStartLine()); 758 functions[i].getBody().writeOut(bc); 759 ExpressionUtil.visitLine(bc, functions[i].getEndLine()); 760 cv.visitWhenAfterBody(bc); 761 } 762 cv.visitAfter(bc); 763 } 764 765 private void writeOutUdfCallInner(BytecodeContext bc,Function[] functions, int offset, int length) throws BytecodeException { 766 NativeSwitch ns=new NativeSwitch(2,NativeSwitch.ARG_REF,-1,-1); 767 768 for(int i=offset;i<length;i++) { 769 ns.addCase(i, functions[i].getBody(),functions[i].getStartLine(),functions[i].getEndLine(),true); 770 } 771 ns._writeOut(bc); 772 } 773 774 775 776 private void writeOutThreadCallInner(BytecodeContext bc,TagThread[] threads, int offset, int length) throws BytecodeException { 777 GeneratorAdapter adapter = bc.getAdapter(); 778 ConditionVisitor cv=new ConditionVisitor(); 779 DecisionIntVisitor div; 780 cv.visitBefore(); 781 //print.ln("functions:"+functions.length); 782 for(int i=offset;i<length;i++) { 783 cv.visitWhenBeforeExpr(); 784 div=new DecisionIntVisitor(); 785 div.visitBegin(); 786 adapter.loadArg(1); 787 div.visitEQ(); 788 adapter.push(i); 789 div.visitEnd(bc); 790 cv.visitWhenAfterExprBeforeBody(bc); 791 Body body = threads[i].getRealBody(); 792 if(body!=null)body.writeOut(bc); 793 cv.visitWhenAfterBody(bc); 794 } 795 cv.visitAfter(bc); 796 } 797 798 private void writeOutInitComponent(BytecodeContext statConstr,BytecodeContext constr,List keys, ClassWriter cw, Tag component) throws BytecodeException { 799 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , INIT_COMPONENT, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 800 BytecodeContext bc=new BytecodeContext(statConstr, constr,externalizer,keys,cw,name,adapter,INIT_COMPONENT,writeLog()); 801 Label methodBegin=new Label(); 802 Label methodEnd=new Label(); 803 804 adapter.visitLocalVariable("this", "L"+name+";", null, methodBegin, methodEnd, 0); 805 adapter.visitLabel(methodBegin); 806 807 // Scope oldData=null; 808 int oldData=adapter.newLocal(Types.VARIABLES); 809 ASMConstants.NULL(adapter); 810 adapter.storeLocal(oldData); 811 812 int localBC=adapter.newLocal(Types.BODY_CONTENT); 813 ConditionVisitor cv=new ConditionVisitor(); 814 cv.visitBefore(); 815 cv.visitWhenBeforeExpr(); 816 adapter.loadArg(1); 817 adapter.invokeVirtual(Types.COMPONENT_IMPL, GET_OUTPUT); 818 cv.visitWhenAfterExprBeforeBody(bc); 819 ASMConstants.NULL(adapter); 820 cv.visitWhenAfterBody(bc); 821 822 cv.visitOtherviseBeforeBody(); 823 adapter.loadArg(0); 824 adapter.invokeVirtual(Types.PAGE_CONTEXT, PUSH_BODY); 825 cv.visitOtherviseAfterBody(); 826 cv.visitAfter(bc); 827 adapter.storeLocal(localBC); 828 829 // c.init(pc,this); 830 adapter.loadArg(1); 831 adapter.loadArg(0); 832 adapter.visitVarInsn(Opcodes.ALOAD, 0); 833 adapter.invokeVirtual(Types.COMPONENT_IMPL, INIT); 834 835 836 //int oldCheckArgs= pc.undefinedScope().setMode(Undefined.MODE_NO_LOCAL_AND_ARGUMENTS); 837 int oldCheckArgs = adapter.newLocal(Types.INT_VALUE); 838 adapter.loadArg(0); 839 adapter.invokeVirtual(Types.PAGE_CONTEXT, UNDEFINED_SCOPE); 840 adapter.push(Undefined.MODE_NO_LOCAL_AND_ARGUMENTS); 841 adapter.invokeInterface(Types.UNDEFINED, SET_MODE); 842 adapter.storeLocal(oldCheckArgs); 843 844 845 TryCatchFinallyVisitor tcf=new TryCatchFinallyVisitor(); 846 tcf.visitTryBegin(bc); 847 // oldData=c.beforeCall(pc); 848 adapter.loadArg(1); 849 adapter.loadArg(0); 850 adapter.invokeVirtual(Types.COMPONENT_IMPL, BEFORE_CALL); 851 adapter.storeLocal(oldData); 852 ExpressionUtil.visitLine(bc, component.getStartLine()); 853 writeOutCallBody(bc,component.getBody(),IFunction.PAGE_TYPE_COMPONENT); 854 ExpressionUtil.visitLine(bc, component.getEndLine()); 855 tcf.visitTryEnd(bc); 856 857 int t=tcf.visitCatchBegin(bc, Types.THROWABLE); 858 // BodyContentUtil.flushAndPop(pc,bc); 859 adapter.loadArg(0); 860 adapter.loadLocal(localBC); 861 adapter.invokeStatic(Types.BODY_CONTENT_UTIL, FLUSH_AND_POP); 862 863 // throw Caster.toPageException(t); 864 adapter.loadLocal(t); 865 adapter.invokeStatic(Types.CASTER, TO_PAGE_EXCEPTION); 866 adapter.throwException(); 867 tcf.visitCatchEnd(bc); 868 869 tcf.visitFinallyBegin(bc); 870 871 // undefined.setMode(oldMode); 872 adapter.loadArg(0); 873 adapter.invokeVirtual(Types.PAGE_CONTEXT, UNDEFINED_SCOPE); 874 adapter.loadLocal(oldCheckArgs,Types.INT_VALUE); 875 adapter.invokeInterface(Types.UNDEFINED, SET_MODE); 876 adapter.pop(); 877 878 // c.afterCall(pc,_oldData); 879 adapter.loadArg(1); 880 adapter.loadArg(0); 881 adapter.loadLocal(oldData); 882 adapter.invokeVirtual(Types.COMPONENT_IMPL, AFTER_CALL); 883 884 885 886 tcf.visitFinallyEnd(bc); 887 adapter.loadArg(0); 888 adapter.loadLocal(localBC); 889 adapter.invokeStatic(Types.BODY_CONTENT_UTIL, CLEAR_AND_POP); 890 891 adapter.returnValue(); 892 adapter.visitLabel(methodEnd); 893 894 adapter.endMethod(); 895 896 } 897 898 private void writeOutInitInterface(BytecodeContext statConstr,BytecodeContext constr,List keys, ClassWriter cw, Tag interf) throws BytecodeException { 899 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , INIT_INTERFACE, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 900 BytecodeContext bc=new BytecodeContext(statConstr, constr,externalizer,keys,cw,name,adapter,INIT_INTERFACE,writeLog()); 901 Label methodBegin=new Label(); 902 Label methodEnd=new Label(); 903 904 adapter.visitLocalVariable("this", "L"+name+";", null, methodBegin, methodEnd, 0); 905 adapter.visitLabel(methodBegin); 906 907 ExpressionUtil.visitLine(bc, interf.getStartLine()); 908 writeOutCallBody(bc,interf.getBody(),IFunction.PAGE_TYPE_INTERFACE); 909 ExpressionUtil.visitLine(bc, interf.getEndLine()); 910 911 adapter.returnValue(); 912 adapter.visitLabel(methodEnd); 913 914 adapter.endMethod(); 915 916 } 917 918 private Tag getComponent() throws BytecodeException { 919 Iterator it = getStatements().iterator(); 920 Statement s; 921 Tag t; 922 while(it.hasNext()) { 923 s=(Statement)it.next(); 924 if(s instanceof Tag) { 925 t=(Tag)s; 926 if(t.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Component"))return t; 927 } 928 } 929 throw new BytecodeException("missing component",getLine()); 930 } 931 private Tag getInterface() throws BytecodeException { 932 Iterator it = getStatements().iterator(); 933 Statement s; 934 Tag t; 935 while(it.hasNext()) { 936 s=(Statement)it.next(); 937 if(s instanceof Tag) { 938 t=(Tag)s; 939 if(t.getTagLibTag().getTagClassName().equals("railo.runtime.tag.Interface"))return t; 940 } 941 } 942 throw new BytecodeException("missing interface",getLine()); 943 } 944 945 private void writeOutFunctionDefaultValueInnerInner(BytecodeContext bc, Function function) throws BytecodeException { 946 GeneratorAdapter adapter = bc.getAdapter(); 947 948 List args = function.getArguments(); 949 950 if(args.size()==0) { 951 adapter.visitInsn(Opcodes.ACONST_NULL); 952 adapter.returnValue(); 953 return; 954 } 955 956 Iterator it = args.iterator(); 957 Argument arg; 958 ConditionVisitor cv=new ConditionVisitor(); 959 DecisionIntVisitor div; 960 cv.visitBefore(); 961 int count=0; 962 while(it.hasNext()) { 963 arg=(Argument) it.next(); 964 cv.visitWhenBeforeExpr(); 965 div=new DecisionIntVisitor(); 966 div.visitBegin(); 967 adapter.loadArg(2); 968 div.visitEQ(); 969 adapter.push(count++); 970 div.visitEnd(bc); 971 cv.visitWhenAfterExprBeforeBody(bc); 972 Expression defaultValue = arg.getDefaultValue(); 973 if(defaultValue!=null) arg.getDefaultValue().writeOut(bc, Expression.MODE_REF); 974 else 975 adapter.visitInsn(Opcodes.ACONST_NULL); 976 adapter.returnValue(); 977 cv.visitWhenAfterBody(bc); 978 } 979 cv.visitOtherviseBeforeBody(); 980 //adapter.visitInsn(ACONST_NULL); 981 //adapter.returnValue(); 982 cv.visitOtherviseAfterBody(); 983 cv.visitAfter(bc); 984 } 985 986 private Function[] getFunctions() { 987 Function[] funcs=new Function[functions.size()]; 988 Iterator it = functions.iterator(); 989 int count=0; 990 while(it.hasNext()) { 991 funcs[count++]=(Function) it.next(); 992 } 993 return funcs; 994 } 995 996 private TagThread[] getThreads() { 997 TagThread[] threads=new TagThread[this.threads.size()]; 998 Iterator it = this.threads.iterator(); 999 int count=0; 1000 while(it.hasNext()) { 1001 threads[count++]=(TagThread) it.next(); 1002 } 1003 return threads; 1004 } 1005 1006 1007 public void _writeOut(BytecodeContext bc) throws BytecodeException { 1008 1009 } 1010 1011 private void writeOutNewComponent(BytecodeContext statConstr,BytecodeContext constr,List keys,ClassWriter cw, Tag component) throws BytecodeException { 1012 1013 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , NEW_COMPONENT_IMPL_INSTANCE, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 1014 BytecodeContext bc=new BytecodeContext(statConstr, constr,externalizer,keys,cw,name,adapter,NEW_COMPONENT_IMPL_INSTANCE,writeLog()); 1015 Label methodBegin=new Label(); 1016 Label methodEnd=new Label(); 1017 1018 adapter.visitLocalVariable("this", "L"+name+";", null, methodBegin, methodEnd, 0); 1019 adapter.visitLabel(methodBegin); 1020 1021 //ExpressionUtil.visitLine(adapter, component.getStartLine()); 1022 1023 int comp=adapter.newLocal(Types.COMPONENT_IMPL); 1024 adapter.newInstance(Types.COMPONENT_IMPL); 1025 adapter.dup(); 1026 1027 Attribute attr; 1028 // ComponentPage 1029 adapter.visitVarInsn(Opcodes.ALOAD, 0); 1030 adapter.checkCast(Types.COMPONENT_PAGE); 1031 1032 // !!! also check CFMLScriptTransformer.addMetaData if you do any change here !!! 1033 1034 // Output 1035 attr = component.removeAttribute("output"); 1036 if(attr!=null) { 1037 ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1038 } 1039 else ASMConstants.NULL(adapter); 1040 1041 // synchronized 1042 attr = component.removeAttribute("synchronized"); 1043 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_VALUE); 1044 else adapter.push(false); 1045 1046 // extends 1047 attr = component.removeAttribute("extends"); 1048 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1049 else adapter.push(""); 1050 1051 // implements 1052 attr = component.removeAttribute("implements"); 1053 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1054 else adapter.push(""); 1055 1056 // hint 1057 attr = component.removeAttribute("hint"); 1058 if(attr!=null) { 1059 Expression value = attr.getValue(); 1060 if(!(value instanceof Literal)){ 1061 value=LitString.toExprString("[runtime expression]"); 1062 } 1063 ExpressionUtil.writeOutSilent(value,bc, Expression.MODE_REF); 1064 } 1065 else adapter.push(""); 1066 1067 // dspName 1068 attr = component.removeAttribute("displayname"); 1069 if(attr==null) attr=component.getAttribute("display"); 1070 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1071 else adapter.push(""); 1072 1073 // callpath 1074 adapter.visitVarInsn(Opcodes.ALOAD, 2); 1075 // realpath 1076 adapter.visitVarInsn(Opcodes.ILOAD, 3); 1077 1078 1079 // style 1080 attr = component.removeAttribute("style"); 1081 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1082 else adapter.push(""); 1083 1084 // persistent 1085 attr = component.removeAttribute("persistent"); 1086 boolean persistent=false; 1087 if(attr!=null) { 1088 persistent=ASMUtil.toBoolean(attr,component.getStartLine()).booleanValue(); 1089 } 1090 1091 // persistent 1092 attr = component.removeAttribute("accessors"); 1093 boolean accessors=false; 1094 if(attr!=null) { 1095 accessors=ASMUtil.toBoolean(attr,component.getStartLine()).booleanValue(); 1096 } 1097 1098 adapter.push(persistent); 1099 adapter.push(accessors); 1100 //ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_VALUE); 1101 1102 //adapter.visitVarInsn(Opcodes.ALOAD, 4); 1103 createMetaDataStruct(bc,component.getAttributes(),component.getMetaData()); 1104 1105 adapter.invokeConstructor(Types.COMPONENT_IMPL, CONSTR_COMPONENT_IMPL); 1106 1107 adapter.storeLocal(comp); 1108 1109 //Component Impl(ComponentPage componentPage,boolean output, String extend, String hint, String dspName) 1110 1111 1112 // initComponent(pc,c); 1113 adapter.visitVarInsn(Opcodes.ALOAD, 0); 1114 adapter.loadArg(0); 1115 adapter.loadLocal(comp); 1116 adapter.invokeVirtual(Types.COMPONENT_PAGE, INIT_COMPONENT); 1117 1118 adapter.visitLabel(methodEnd); 1119 1120 // return component; 1121 adapter.loadLocal(comp); 1122 1123 adapter.returnValue(); 1124 //ExpressionUtil.visitLine(adapter, component.getEndLine()); 1125 adapter.endMethod(); 1126 1127 1128 } 1129 1130 private void writeOutNewInterface(BytecodeContext statConstr,BytecodeContext constr,List keys,ClassWriter cw, Tag interf) throws BytecodeException { 1131 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , NEW_INTERFACE_IMPL_INSTANCE, null, new Type[]{Types.PAGE_EXCEPTION}, cw); 1132 BytecodeContext bc=new BytecodeContext(statConstr, constr,externalizer,keys,cw,name,adapter,NEW_INTERFACE_IMPL_INSTANCE,writeLog()); 1133 Label methodBegin=new Label(); 1134 Label methodEnd=new Label(); 1135 1136 1137 adapter.visitLocalVariable("this", "L"+name+";", null, methodBegin, methodEnd, 0); 1138 adapter.visitLabel(methodBegin); 1139 1140 //ExpressionUtil.visitLine(adapter, interf.getStartLine()); 1141 1142 int comp=adapter.newLocal(Types.INTERFACE_IMPL); 1143 1144 1145 adapter.newInstance(Types.INTERFACE_IMPL); 1146 adapter.dup(); 1147 1148 1149 Attribute attr; 1150 // Interface Page 1151 adapter.visitVarInsn(Opcodes.ALOAD, 0); 1152 adapter.checkCast(Types.INTERFACE_PAGE); 1153 1154 // extened 1155 attr = interf.removeAttribute("extends"); 1156 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1157 else adapter.push(""); 1158 1159 // hint 1160 attr = interf.removeAttribute("hint"); 1161 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1162 else adapter.push(""); 1163 1164 // dspName 1165 attr = interf.removeAttribute("displayname"); 1166 if(attr==null) attr=interf.getAttribute("display"); 1167 if(attr!=null) ExpressionUtil.writeOutSilent(attr.getValue(),bc, Expression.MODE_REF); 1168 else adapter.push(""); 1169 1170 1171 // callpath 1172 adapter.visitVarInsn(Opcodes.ALOAD, 1); 1173 // realpath 1174 adapter.visitVarInsn(Opcodes.ILOAD, 2); 1175 1176 // interface udfs 1177 adapter.visitVarInsn(Opcodes.ALOAD, 3); 1178 1179 createMetaDataStruct(bc,interf.getAttributes(),interf.getMetaData()); 1180 1181 1182 adapter.invokeConstructor(Types.INTERFACE_IMPL, CONSTR_INTERFACE_IMPL); 1183 1184 adapter.storeLocal(comp); 1185 1186 1187 1188 // initInterface(pc,c); 1189 adapter.visitVarInsn(Opcodes.ALOAD, 0); 1190 //adapter.loadArg(0); 1191 adapter.loadLocal(comp); 1192 adapter.invokeVirtual(Types.INTERFACE_PAGE, INIT_INTERFACE); 1193 1194 adapter.visitLabel(methodEnd); 1195 1196 1197 // return interface; 1198 adapter.loadLocal(comp); 1199 1200 adapter.returnValue(); 1201 //ExpressionUtil.visitLine(adapter, interf.getEndLine()); 1202 adapter.endMethod(); 1203 1204 1205 } 1206 1207 1208 1209 public static void createMetaDataStruct(BytecodeContext bc, Map attrs, Map meta) throws BytecodeException { 1210 1211 1212 GeneratorAdapter adapter = bc.getAdapter(); 1213 if((attrs==null || attrs.size()==0) && (meta==null || meta.size()==0)){ 1214 ASMConstants.NULL(bc.getAdapter()); 1215 bc.getAdapter().cast(Types.OBJECT,STRUCT_IMPL); 1216 return; 1217 } 1218 1219 int sct=adapter.newLocal(STRUCT_IMPL); 1220 adapter.newInstance(STRUCT_IMPL); 1221 adapter.dup(); 1222 adapter.invokeConstructor(STRUCT_IMPL, INIT_STRUCT_IMPL); 1223 adapter.storeLocal(sct); 1224 if(meta!=null) { 1225 _createMetaDataStruct(bc,adapter,sct,meta); 1226 } 1227 if(attrs!=null) { 1228 _createMetaDataStruct(bc,adapter,sct,attrs); 1229 } 1230 1231 1232 adapter.loadLocal(sct); 1233 } 1234 1235 private static void _createMetaDataStruct(BytecodeContext bc, GeneratorAdapter adapter, int sct, Map attrs) throws BytecodeException { 1236 Attribute attr; 1237 Iterator it = attrs.entrySet().iterator(); 1238 Entry entry; 1239 while(it.hasNext()){ 1240 entry = (Map.Entry)it.next(); 1241 attr=(Attribute) entry.getValue(); 1242 adapter.loadLocal(sct); 1243 adapter.push(attr.getName()); 1244 if(attr.getValue() instanceof Literal) 1245 ExpressionUtil.writeOutSilent(attr.getValue(),bc,Expression.MODE_REF); 1246 else 1247 adapter.push("[runtime expression]"); 1248 1249 adapter.invokeVirtual(STRUCT_IMPL, SET_EL); 1250 adapter.pop(); 1251 } 1252 } 1253 1254 private void writeOutCall(BytecodeContext statConstr,BytecodeContext constr,List keys,ClassWriter cw) throws BytecodeException { 1255 //GeneratorAdapter adapter = bc.getAdapter(); 1256 GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , CALL, null, new Type[]{Types.THROWABLE}, cw); 1257 Label methodBegin=new Label(); 1258 Label methodEnd=new Label(); 1259 1260 adapter.visitLocalVariable("this", "L"+name+";", null, methodBegin, methodEnd, 0); 1261 adapter.visitLabel(methodBegin); 1262 1263 writeOutCallBody(new BytecodeContext(statConstr, constr,externalizer,keys,cw,name,adapter,CALL,writeLog()),this,IFunction.PAGE_TYPE_REGULAR); 1264 1265 adapter.visitLabel(methodEnd); 1266 adapter.returnValue(); 1267 adapter.endMethod(); 1268 } 1269 1270 1271 private void writeOutCallBody(BytecodeContext bc,Body body, int pageType) throws BytecodeException { 1272 // Other 1273 List<IFunction> functions=new ArrayList<IFunction>(); 1274 getFunctions(functions,bc,body,pageType); 1275 1276 String className = Types.UDF_PROPERTIES_ARRAY.toString(); 1277 //FieldVisitor fv = bc.getClassWriter().visitField(Opcodes.ACC_PRIVATE , "udfs",className , null, null); 1278 //fv.visitEnd(); 1279 1280 BytecodeContext constr = bc.getConstructor(); 1281 GeneratorAdapter cga = constr.getAdapter(); 1282 1283 cga.visitVarInsn(Opcodes.ALOAD, 0); 1284 cga.push(functions.size()); 1285 //cga.visitTypeInsn(Opcodes.ANEWARRAY, Types.UDF_PROPERTIES.toString()); 1286 cga.newArray(Types.UDF_PROPERTIES); 1287 cga.visitFieldInsn(Opcodes.PUTFIELD, bc.getClassName(), "udfs", className); 1288 1289 1290 Iterator<IFunction> it = functions.iterator(); 1291 while(it.hasNext()){ 1292 it.next().writeOut(bc, pageType); 1293 } 1294 1295 if(pageType==IFunction.PAGE_TYPE_COMPONENT) { 1296 GeneratorAdapter adapter = bc.getAdapter(); 1297 adapter.loadArg(1); 1298 adapter.loadArg(0); 1299 adapter.visitVarInsn(Opcodes.ALOAD, 0); 1300 adapter.invokeVirtual(Types.COMPONENT_IMPL, CHECK_INTERFACE); 1301 1302 } 1303 if(pageType!=IFunction.PAGE_TYPE_INTERFACE){ 1304 BodyBase.writeOut(bc.getStaticConstructor(),bc.getConstructor(),bc.getKeys(),body.getStatements(), bc); 1305 } 1306 } 1307 1308 private static void getImports(List<String> list,Body body) throws BytecodeException { 1309 if(ASMUtil.isEmpty(body)) return; 1310 Statement stat; 1311 List stats = body.getStatements(); 1312 int len=stats.size(); 1313 for(int i=0;i<len;i++) { 1314 stat = (Statement)stats.get(i); 1315 1316 // IFunction 1317 if(stat instanceof TagImport && !StringUtil.isEmpty(((TagImport)stat).getPath(),true)) { 1318 ImportDefintion id = ImportDefintion.getInstance(((TagImport) stat).getPath(), null); 1319 if(id!=null && (!list.contains(id.toString()) && !list.contains(id.getPackage()+".*"))){ 1320 list.add(id.toString()); 1321 } 1322 stats.remove(i); 1323 len--; 1324 i--; 1325 1326 } 1327 else if(stat instanceof HasBody) getImports(list, ((HasBody)stat).getBody()); 1328 else if(stat instanceof HasBodies) { 1329 Body[] bodies=((HasBodies)stat).getBodies(); 1330 for(int y=0;y<bodies.length;y++) { 1331 getImports(list,bodies[y]); 1332 } 1333 } 1334 } 1335 } 1336 1337 1338 private static void getFunctions(List<IFunction> functions,BytecodeContext bc, Body body, int pageType) throws BytecodeException { 1339 //writeOutImports(bc, body, pageType); 1340 if(ASMUtil.isEmpty(body)) return; 1341 Statement stat; 1342 List stats = body.getStatements(); 1343 int len=stats.size(); 1344 for(int i=0;i<len;i++) { 1345 stat = (Statement)stats.get(i); 1346 1347 // IFunction 1348 if(stat instanceof IFunction) { 1349 functions.add((IFunction)stat); 1350 //((IFunction)stat).writeOut(bc,pageType); 1351 stats.remove(i); 1352 len--; 1353 i--; 1354 } 1355 else if(stat instanceof HasBody) getFunctions(functions,bc, ((HasBody)stat).getBody(), pageType); 1356 else if(stat instanceof HasBodies) { 1357 Body[] bodies=((HasBodies)stat).getBodies(); 1358 for(int y=0;y<bodies.length;y++) { 1359 getFunctions(functions,bc,bodies[y] , pageType); 1360 } 1361 1362 } 1363 } 1364 } 1365 1366 1367 /** 1368 * @return the source 1369 */ 1370 public String getSource() { 1371 return path; 1372 } 1373 1374 /** 1375 * @return if it is a component 1376 */ 1377 public boolean isComponent() { 1378 return isComponent; 1379 } 1380 1381 /** 1382 * set if the page is a component or not 1383 * @param cfc 1384 */ 1385 public void setIsComponent(boolean isComponent) { 1386 this.isComponent = isComponent; 1387 } 1388 1389 /** 1390 * @return if it is a component 1391 */ 1392 public boolean isInterface() { 1393 return isInterface; 1394 } 1395 1396 1397 public boolean isPage() { 1398 return !isInterface && !isComponent; 1399 } 1400 1401 /** 1402 * set if the page is a component or not 1403 * @param cfc 1404 */ 1405 public void setIsInterface(boolean isInterface) { 1406 this.isInterface = isInterface; 1407 } 1408 /** 1409 * @return the lastModifed 1410 */ 1411 public long getLastModifed() { 1412 return lastModifed; 1413 } 1414 1415 1416 public int addFunction(IFunction function) { 1417 functions.add(function); 1418 return functions.size()-1; 1419 } 1420 1421 public int addThread(TagThread thread) { 1422 threads.add(thread); 1423 return threads.size()-1; 1424 } 1425 1426 public static byte[] setSourceLastModified(byte[] barr, long lastModified) { 1427 ClassReader cr = new ClassReader(barr); 1428 ClassWriter cw = new ClassWriter(true); 1429 ClassAdapter ca = new SourceLastModifiedClassAdapter(cw,lastModified); 1430 cr.accept(ca, true); 1431 return cw.toByteArray(); 1432 } 1433 1434 1435 1436 } 1437 class SourceLastModifiedClassAdapter extends ClassAdapter { 1438 1439 private long lastModified; 1440 public SourceLastModifiedClassAdapter(ClassWriter cw, long lastModified) { 1441 super(cw); 1442 this.lastModified=lastModified; 1443 } 1444 public MethodVisitor visitMethod(int access,String name, String desc, String signature, String[] exceptions) { 1445 1446 if(!name.equals("getSourceLastModified"))return super.visitMethod(access,name, desc, signature, exceptions); 1447 1448 MethodVisitor mv = cv.visitMethod(access,name, desc, signature, exceptions); 1449 mv.visitCode(); 1450 mv.visitLdcInsn(Long.valueOf(lastModified)); 1451 mv.visitInsn(Opcodes.LRETURN); 1452 mv.visitEnd(); 1453 return mv; 1454 } 1455 1456 }