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