001 package railo.runtime; 002 003 import java.io.Externalizable; 004 import java.io.IOException; 005 import java.io.ObjectInput; 006 import java.io.ObjectOutput; 007 import java.lang.ref.SoftReference; 008 import java.util.ArrayList; 009 import java.util.Date; 010 import java.util.HashMap; 011 import java.util.HashSet; 012 import java.util.Iterator; 013 import java.util.LinkedHashMap; 014 import java.util.Map; 015 import java.util.Set; 016 017 import javax.servlet.http.Cookie; 018 019 import railo.commons.io.DevNullOutputStream; 020 import railo.commons.lang.CFTypes; 021 import railo.commons.lang.ExceptionUtil; 022 import railo.commons.lang.Pair; 023 import railo.commons.lang.SizeOf; 024 import railo.commons.lang.StringUtil; 025 import railo.commons.lang.types.RefBoolean; 026 import railo.commons.lang.types.RefBooleanImpl; 027 import railo.runtime.component.ComponentLoader; 028 import railo.runtime.component.DataMember; 029 import railo.runtime.component.InterfaceCollection; 030 import railo.runtime.component.Member; 031 import railo.runtime.component.Property; 032 import railo.runtime.config.ConfigImpl; 033 import railo.runtime.config.ConfigWeb; 034 import railo.runtime.config.ConfigWebImpl; 035 import railo.runtime.converter.ScriptConverter; 036 import railo.runtime.debug.DebugEntry; 037 import railo.runtime.dump.DumpData; 038 import railo.runtime.dump.DumpProperties; 039 import railo.runtime.dump.DumpTable; 040 import railo.runtime.dump.DumpTablePro; 041 import railo.runtime.dump.DumpUtil; 042 import railo.runtime.dump.SimpleDumpData; 043 import railo.runtime.engine.ThreadLocalPageContext; 044 import railo.runtime.exp.ApplicationException; 045 import railo.runtime.exp.DeprecatedException; 046 import railo.runtime.exp.ExpressionException; 047 import railo.runtime.exp.PageException; 048 import railo.runtime.exp.PageRuntimeException; 049 import railo.runtime.interpreter.CFMLExpressionInterpreter; 050 import railo.runtime.op.Caster; 051 import railo.runtime.op.Duplicator; 052 import railo.runtime.op.Operator; 053 import railo.runtime.op.ThreadLocalDuplication; 054 import railo.runtime.op.date.DateCaster; 055 import railo.runtime.thread.ThreadUtil; 056 import railo.runtime.type.ArrayImpl; 057 import railo.runtime.type.Collection; 058 import railo.runtime.type.FunctionArgument; 059 import railo.runtime.type.KeyImpl; 060 import railo.runtime.type.List; 061 import railo.runtime.type.Sizeable; 062 import railo.runtime.type.Struct; 063 import railo.runtime.type.StructImpl; 064 import railo.runtime.type.UDF; 065 import railo.runtime.type.UDFGSProperty; 066 import railo.runtime.type.UDFImpl; 067 import railo.runtime.type.UDFProperties; 068 import railo.runtime.type.cfc.ComponentAccess; 069 import railo.runtime.type.comparator.ArrayOfStructComparator; 070 import railo.runtime.type.dt.DateTime; 071 import railo.runtime.type.scope.Argument; 072 import railo.runtime.type.scope.ArgumentImpl; 073 import railo.runtime.type.scope.ArgumentIntKey; 074 import railo.runtime.type.scope.Variables; 075 import railo.runtime.type.util.ArrayUtil; 076 import railo.runtime.type.util.ComponentUtil; 077 import railo.runtime.type.util.PropertyFactory; 078 import railo.runtime.type.util.StructSupport; 079 import railo.runtime.type.util.StructUtil; 080 import railo.runtime.util.ArrayIterator; 081 082 /** 083 * %**% 084 * MUST add handling for new attributes (style, namespace, serviceportname, porttypename, wsdlfile, bindingname, and output) 085 */ 086 public final class ComponentImpl extends StructSupport implements Externalizable,ComponentAccess,coldfusion.runtime.TemplateProxy,Sizeable { 087 088 089 private ComponentProperties properties; 090 private Map<Key,Member> _data; 091 private Map<Key,UDF> _udfs; 092 093 ComponentImpl top=this; 094 ComponentImpl base; 095 //private ComponentPage componentPage; 096 private PageSource pageSource; 097 private ComponentScope scope; 098 099 // for all the same 100 private int dataMemberDefaultAccess; 101 private boolean triggerDataMember; 102 103 // state control of component 104 boolean isInit=false; 105 106 private InterfaceCollection interfaceCollection; 107 108 private boolean useShadow; 109 boolean afterConstructor; 110 private Map<Key,UDF> constructorUDFs; 111 112 private static final Key TO_DATETIME = KeyImpl.intern("_toDateTime"); 113 private static final Key TO_NUMERIC = KeyImpl.intern("_toNumeric"); 114 private static final Key TO_BOOLEAN = KeyImpl.intern("_toBoolean"); 115 private static final Key TO_STRING = KeyImpl.intern("_toString"); 116 117 private static final Key ON_MISSING_METHOD = KeyImpl.intern("onmissingmethod"); 118 119 protected static final Key EXTENDS = KeyImpl.intern("extends"); 120 protected static final Key IMPLEMENTS = KeyImpl.intern("implements"); 121 protected static final Key FUNCTIONS = KeyImpl.intern("functions"); 122 protected static final Key FULLNAME = KeyImpl.intern("fullname"); 123 protected static final Key SKELETON = KeyImpl.intern("skeleton"); 124 protected static final Key PROPERTIES = KeyImpl.intern("properties"); 125 private static final Key MAPPED_SUPER_CLASS = KeyImpl.intern("mappedSuperClass"); 126 private static final Key PERSISTENT = KeyImpl.intern("persistent"); 127 private static final Key ACCESSORS = KeyImpl.intern("accessors"); 128 private static final Key SYNCRONIZED = KeyImpl.intern("synchronized"); 129 protected static final Key DISPLAY_NAME = KeyImpl.intern("displayname"); 130 131 public long sizeOf() { 132 return 133 SizeOf.size(properties)+ 134 SizeOf.size(_data)+ 135 SizeOf.size(scope)+ 136 SizeOf.size(dataMemberDefaultAccess)+ 137 SizeOf.size(triggerDataMember)+ 138 SizeOf.size(false)+ 139 SizeOf.size(interfaceCollection)+ 140 SizeOf.size(useShadow)+ 141 SizeOf.size(afterConstructor)+ 142 SizeOf.size(base); 143 } 144 145 /** 146 * Constructor of the Component, USED ONLY FOR DESERIALIZE 147 */ 148 public ComponentImpl() { 149 } 150 151 /** 152 * Constructor of the class 153 * @param componentPage 154 * @param output 155 * @param _synchronized 156 * @param extend 157 * @param implement 158 * @param hint 159 * @param dspName 160 * @param callPath 161 * @param realPath 162 * @param style 163 * @param meta 164 * @throws ApplicationException 165 */ 166 167 public ComponentImpl(ComponentPage componentPage,Boolean output,boolean _synchronized, 168 String extend, String implement, String hint, String dspName,String callPath, boolean realPath, 169 String style,StructImpl meta) throws ApplicationException { 170 this(componentPage,output,_synchronized, 171 extend, implement, hint, dspName,callPath, realPath, style,false, false,meta); 172 } 173 174 public ComponentImpl(ComponentPage componentPage,Boolean output,boolean _synchronized, 175 String extend, String implement, String hint, String dspName,String callPath, boolean realPath, 176 String style,boolean persistent,StructImpl meta) throws ApplicationException { 177 this(componentPage,output,_synchronized, 178 extend, implement, hint, dspName,callPath, realPath, style,persistent, false,meta); 179 } 180 181 public ComponentImpl(ComponentPage componentPage,Boolean output,boolean _synchronized, 182 String extend, String implement, String hint, String dspName,String callPath, boolean realPath, 183 String style,boolean persistent,boolean accessors,StructImpl meta) throws ApplicationException { 184 this.properties=new ComponentProperties(dspName,extend.trim(),implement,hint,output,callPath,realPath,_synchronized,null,persistent,accessors,meta); 185 //this.componentPage=componentPage instanceof ComponentPageProxy?componentPage:PageProxy.toProxy(componentPage); 186 this.pageSource=componentPage.getPageSource(); 187 188 if(!StringUtil.isEmpty(style) && !"rpc".equals(style)) 189 throw new ApplicationException("style ["+style+"] is not supported, only the following styles are supported [rpc]"); 190 } 191 192 193 /** 194 * @see railo.runtime.type.Collection#duplicate(boolean) 195 196 public synchronized Collection duplicatex(boolean deepCopy) { 197 ComponentImpl c=new ClonedComponent(this,deepCopy); 198 return c; 199 }*/ 200 201 public Collection duplicate(boolean deepCopy) { 202 ComponentImpl top= _duplicate(deepCopy,true); 203 setTop(top,top); 204 205 206 return top; 207 } 208 209 210 211 212 private ComponentImpl _duplicate( boolean deepCopy, boolean isTop) { 213 ComponentImpl trg=new ComponentImpl(); 214 ThreadLocalDuplication.set(this, trg); 215 try{ 216 // attributes 217 trg.pageSource=pageSource; 218 trg.triggerDataMember=triggerDataMember; 219 trg.useShadow=useShadow; 220 trg.afterConstructor=afterConstructor; 221 trg.dataMemberDefaultAccess=dataMemberDefaultAccess; 222 trg.properties=properties.duplicate(); 223 trg.isInit=isInit; 224 trg.interfaceCollection=interfaceCollection; 225 226 boolean useShadow=scope instanceof ComponentScopeShadow; 227 if(!useShadow)trg.scope=new ComponentScopeThis(trg); 228 229 if(base!=null){ 230 trg.base=base._duplicate(deepCopy,false); 231 232 trg._data=trg.base._data; 233 trg._udfs=duplicateUTFMap(this,trg, _udfs,new HashMap<Key,UDF>(trg.base._udfs)); 234 235 if(useShadow) trg.scope=new ComponentScopeShadow(trg,(ComponentScopeShadow)trg.base.scope,false); 236 } 237 else { 238 // clone data member, ignore udfs for the moment 239 trg._data=duplicateDataMember(trg, _data, new HashMap(), deepCopy); 240 trg._udfs=duplicateUTFMap(this,trg, _udfs,new HashMap<Key, UDF>()); 241 242 if(useShadow) { 243 ComponentScopeShadow css = (ComponentScopeShadow)scope; 244 trg.scope=new ComponentScopeShadow(trg,duplicateDataMember(trg,css.getShadow(),new HashMap(),deepCopy)); 245 } 246 } 247 248 // at the moment this makes no sense, becuae this map is no more used after constructor has runned and for a clone the constructo is not executed, but perhaps this is used in future 249 if(constructorUDFs!=null){ 250 trg.constructorUDFs=new HashMap<Collection.Key, UDF>(); 251 addUDFS(trg, constructorUDFs, trg.constructorUDFs); 252 } 253 254 255 if(isTop) { 256 setTop(trg,trg); 257 258 addUDFS(trg,_data,trg._data); 259 if(useShadow){ 260 addUDFS(trg,((ComponentScopeShadow)scope).getShadow(),((ComponentScopeShadow)trg.scope).getShadow()); 261 } 262 } 263 264 265 266 267 } 268 finally { 269 ThreadLocalDuplication.remove(this); 270 } 271 272 return trg; 273 } 274 275 276 private static void addUDFS(ComponentImpl trgComp, Map src, Map trg) { 277 Iterator it = src.entrySet().iterator(); 278 Map.Entry entry; 279 Object key,value; 280 UDF udf; 281 ComponentImpl comp,owner; 282 boolean done; 283 while(it.hasNext()){ 284 entry=(Entry) it.next(); 285 key=entry.getKey(); 286 value=entry.getValue(); 287 if(value instanceof UDF) { 288 udf=(UDF) value; 289 done=false; 290 // get udf from _udf 291 owner = (ComponentImpl)udf.getOwnerComponent(); 292 if(owner!=null) { 293 comp=trgComp; 294 do{ 295 if(owner.pageSource==comp.pageSource) 296 break; 297 } 298 while((comp=comp.base)!=null); 299 if(comp!=null) { 300 value=comp._udfs.get(key); 301 trg.put(key, value); 302 done=true; 303 } 304 } 305 // udf with no owner 306 if(!done) 307 trg.put(key, udf.duplicate()); 308 309 //print.o(owner.pageSource.getComponentName()+":"+udf.getFunctionName()); 310 } 311 } 312 } 313 314 /** 315 * duplicate the datamember in the map, ignores the udfs 316 * @param c 317 * @param map 318 * @param newMap 319 * @param deepCopy 320 * @return 321 */ 322 public static Map duplicateDataMember(ComponentImpl c,Map map,Map newMap,boolean deepCopy){ 323 Iterator it=map.entrySet().iterator(); 324 Map.Entry entry; 325 Object value; 326 while(it.hasNext()) { 327 entry=(Entry) it.next(); 328 value=entry.getValue(); 329 330 if(!(value instanceof UDF)) { 331 if(deepCopy) value=Duplicator.duplicate(value,deepCopy); 332 newMap.put(entry.getKey(),value); 333 } 334 } 335 return newMap; 336 } 337 338 public static Map<Key, UDF> duplicateUTFMap(ComponentImpl src,ComponentImpl trg,Map<Key,UDF> srcMap, Map<Key, UDF> trgMap){ 339 Iterator<Entry<Key, UDF>> it = srcMap.entrySet().iterator(); 340 Map.Entry<Key, UDF> entry; 341 UDF udf; 342 while(it.hasNext()) { 343 entry=it.next(); 344 udf=entry.getValue(); 345 346 if(udf.getOwnerComponent()==src) { 347 udf=((UDFImpl)entry.getValue()).duplicate(trg); 348 trgMap.put(entry.getKey(),udf); 349 } 350 351 } 352 return trgMap; 353 } 354 355 356 /** 357 * initalize the Component 358 * @param pageContext 359 * @param componentPage 360 * @throws PageException 361 */ 362 public void init(PageContext pageContext, ComponentPage componentPage) throws PageException { 363 //this.componentPage=componentPage; 364 this.pageSource=componentPage.getPageSource(); 365 366 // extends 367 if(!StringUtil.isEmpty(properties.extend)) { 368 base= ComponentLoader.loadComponent(pageContext,properties.extend,Boolean.TRUE,null); 369 } 370 else { 371 Page p=((ConfigWebImpl)pageContext.getConfig()).getBaseComponentPage(pageContext); 372 if(!componentPage.getPageSource().equals(p.getPageSource())) { 373 base=ComponentLoader.loadComponent(pageContext,p,p.getPageSource(),"Component",false); 374 } 375 } 376 377 if(base!=null){ 378 this.dataMemberDefaultAccess=base.dataMemberDefaultAccess; 379 this.triggerDataMember=base.triggerDataMember; 380 _data=base._data; 381 _udfs=new HashMap<Key,UDF>(base._udfs); 382 setTop(this,base); 383 } 384 else { 385 this.dataMemberDefaultAccess=pageContext.getConfig().getComponentDataMemberDefaultAccess(); 386 this.triggerDataMember=pageContext.getConfig().getTriggerComponentDataMember(); 387 _udfs=new HashMap<Key,UDF>(); 388 _data=new HashMap<Key,Member>(); 389 } 390 391 // implements 392 if(!StringUtil.isEmpty(properties.implement)) { 393 interfaceCollection=new InterfaceCollection((PageContextImpl)pageContext,properties.implement); 394 } 395 396 // scope 397 if(useShadow=pageContext.getConfig().useComponentShadow()) { 398 if(base==null) scope=new ComponentScopeShadow(this,new HashMap<Key,Object>()); 399 else scope=new ComponentScopeShadow(this,(ComponentScopeShadow)base.scope,false); 400 } 401 else { 402 scope=new ComponentScopeThis(this); 403 } 404 initProperties(); 405 } 406 407 public void checkInterface(PageContext pc, ComponentPage componentPage) throws PageException { 408 if(interfaceCollection==null || interfaceCollection.lastUpdate()<=componentPage.lastCheck()) return; 409 410 Iterator it = interfaceCollection.getUdfs().entrySet().iterator(); 411 Map.Entry entry; 412 UDFImpl iUdf,cUdf; 413 FunctionArgument[] iFA,cFA; 414 while(it.hasNext()){ 415 416 entry=(Entry) it.next(); 417 iUdf=(UDFImpl) entry.getValue(); 418 cUdf=(UDFImpl) _udfs.get(entry.getKey()); 419 420 // UDF does not exist 421 if(cUdf==null ) { 422 throw new ExpressionException( 423 "component ["+componentPage.getPageSource().getDisplayPath()+ 424 "] does not implement the function ["+iUdf.toString().toLowerCase()+"] of the interface ["+ 425 iUdf.getPageSource().getDisplayPath()+"]"); 426 427 } 428 429 iFA=iUdf.getFunctionArguments(); 430 cFA=cUdf.getFunctionArguments(); 431 // access 432 if(cUdf.getAccess()>Component.ACCESS_PUBLIC){ 433 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 434 "access ["+ComponentUtil.toStringAccess(cUdf.getAccess())+"] has to be at least [public]"); 435 } 436 437 // return type 438 if(iUdf.getReturnType()!=cUdf.getReturnType()){ 439 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 440 "return type ["+cUdf.getReturnTypeAsString()+"] does not match interface function return type ["+iUdf.getReturnTypeAsString()+"]"); 441 } 442 // none base types 443 if(iUdf.getReturnType()==CFTypes.TYPE_UNKNOW && !iUdf.getReturnTypeAsString().equalsIgnoreCase(cUdf.getReturnTypeAsString())) { 444 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 445 "return type ["+cUdf.getReturnTypeAsString()+"] does not match interface function return type ["+iUdf.getReturnTypeAsString()+"]"); 446 } 447 // output 448 if(iUdf.getOutput()!=cUdf.getOutput()){ 449 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 450 "output does not match interface function output definition"); 451 } 452 453 // arguments 454 if(iFA.length!=cFA.length) { 455 throw new ExpressionException( _getErrorMessage(cUdf,iUdf),"not the same argument count"); 456 } 457 458 for(int i=0;i<iFA.length;i++) { 459 // type 460 if(iFA[i].getType()!=cFA[i].getType()){ 461 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 462 "argument type ["+cFA[i].getTypeAsString()+"] does not match interface function argument type ["+iFA[i].getTypeAsString()+"]"); 463 } 464 // none base types 465 if(iFA[i].getType()==CFTypes.TYPE_UNKNOW && !iFA[i].getTypeAsString().equalsIgnoreCase(cFA[i].getTypeAsString())) { 466 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 467 "argument type ["+cFA[i].getTypeAsString()+"] does not match interface function argument type ["+iFA[i].getTypeAsString()+"]"); 468 } 469 // name 470 if(!iFA[i].getName().equalsIgnoreCase(cFA[i].getName())){ 471 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 472 "argument name ["+cFA[i].getName()+"] does not match interface function argument name ["+iFA[i].getName()+"]"); 473 } 474 // required 475 if(iFA[i].isRequired()!=cFA[i].isRequired()){ 476 throw new ExpressionException( _getErrorMessage(cUdf,iUdf), 477 "argument ["+cFA[i].getName()+"] should "+(iFA[i].isRequired()?"":"not ")+"be required"); 478 } 479 } 480 } 481 componentPage.ckecked(); 482 } 483 484 private String _getErrorMessage(UDFImpl cUdf,UDFImpl iUdf) { 485 return "function ["+cUdf.toString().toLowerCase()+"] of component " + 486 "["+pageSource.getDisplayPath()+"]" + 487 " does not match the function declarition ["+iUdf.toString().toLowerCase()+"] of the interface " + 488 "["+iUdf.getPageSource().getDisplayPath()+"]"; 489 } 490 491 492 private static void setTop(ComponentImpl top,ComponentImpl trg) { 493 while(trg!=null){ 494 trg.top=top; 495 trg=trg.base; 496 } 497 } 498 499 Object _call(PageContext pc, Collection.Key key, Struct namedArgs, Object[] args,boolean superAccess) throws PageException { 500 Member member=getMember(pc,key,false, superAccess); 501 if(member instanceof UDF) { 502 return _call(pc,(UDF)member,namedArgs,args); 503 } 504 return onMissingMethod(pc, -1, member, key.getString(), args, namedArgs, superAccess); 505 } 506 507 Object _call(PageContext pc, int access, Collection.Key key, Struct namedArgs, Object[] args,boolean superAccess) throws PageException { 508 Member member=getMember(access,key,false,superAccess); 509 if(member instanceof UDF) { 510 return _call(pc,(UDF)member,namedArgs,args); 511 } 512 return onMissingMethod(pc, access, member, key.getString(), args, namedArgs, superAccess); 513 } 514 515 public Object onMissingMethod(PageContext pc, int access,Member member,String name,Object _args[],Struct _namedArgs, boolean superAccess) throws PageException { 516 Member ommm = access==-1? 517 getMember(pc,ON_MISSING_METHOD,false, superAccess): 518 getMember(access,ON_MISSING_METHOD,false, superAccess); 519 if(ommm instanceof UDF) { 520 Argument args=new ArgumentImpl(); 521 if(_args!=null) { 522 for(int i=0;i<_args.length;i++) { 523 args.setEL(ArgumentIntKey.init(i+1), _args[i]); 524 } 525 } 526 else if(_namedArgs!=null) { 527 UDFImpl.argumentCollection(_namedArgs, new FunctionArgument[]{}); 528 Key[] keys = _namedArgs.keys(); 529 for(int i=0;i<keys.length;i++) { 530 args.setEL(keys[i],_namedArgs.get(keys[i],null)); 531 } 532 } 533 534 //Struct newArgs=new StructImpl(StructImpl.TYPE_SYNC); 535 //newArgs.setEL(MISSING_METHOD_NAME, name); 536 //newArgs.setEL(MISSING_METHOD_ARGS, args); 537 Object[] newArgs=new Object[]{name,args}; 538 539 return _call(pc,(UDF)ommm,null,newArgs); 540 } 541 if(member==null)throw ComponentUtil.notFunction(this, KeyImpl.init(name), null,access); 542 throw ComponentUtil.notFunction(this, KeyImpl.init(name), member.getValue(),access); 543 } 544 545 Object _call(PageContext pc, UDF udf, Struct namedArgs, Object[] args) throws PageException { 546 547 Object rtn=null; 548 Variables parent=null; 549 550 // INFO duplicate code is for faster execution -> less contions 551 552 553 // debug yes 554 if(pc.getConfig().debug()) { 555 DebugEntry debugEntry=pc.getDebugger().getEntry(pc,pageSource,udf.getFunctionName());//new DebugEntry(src,udf.getFunctionName()); 556 int currTime=pc.getExecutionTime(); 557 long time=System.currentTimeMillis(); 558 559 // sync yes 560 if(top.properties._synchronized){ 561 synchronized (this) { 562 try { 563 parent=beforeCall(pc);// FUTURE add to interface 564 if(args!=null)rtn=udf.call(pc,args,true); 565 else rtn=udf.callWithNamedValues(pc,namedArgs,true); 566 } 567 finally { 568 pc.setVariablesScope(parent); 569 int diff= ((int)(System.currentTimeMillis()-time)-(pc.getExecutionTime()-currTime)); 570 pc.setExecutionTime(pc.getExecutionTime()+diff); 571 debugEntry.updateExeTime(diff); 572 } 573 } 574 } 575 576 // sync no 577 else { 578 try { 579 parent=beforeCall(pc);// FUTURE add to interface 580 if(args!=null)rtn=udf.call(pc,args,true); 581 else rtn=udf.callWithNamedValues(pc,namedArgs,true); 582 } 583 finally { 584 pc.setVariablesScope(parent); 585 int diff= ((int)(System.currentTimeMillis()-time)-(pc.getExecutionTime()-currTime)); 586 pc.setExecutionTime(pc.getExecutionTime()+diff); 587 debugEntry.updateExeTime(diff); 588 } 589 } 590 591 592 } 593 594 // debug no 595 else { 596 597 // sync yes 598 if(top.properties._synchronized){ 599 synchronized (this) { 600 try { 601 parent=beforeCall(pc); // FUTURE add to interface 602 if(args!=null)rtn=udf.call(pc,args,true); 603 else rtn=udf.callWithNamedValues(pc,namedArgs,true); 604 } 605 finally { 606 pc.setVariablesScope(parent); 607 } 608 } 609 } 610 611 // sync no 612 else { 613 try { 614 parent=beforeCall(pc); // FUTURE add to interface 615 if(args!=null)rtn=udf.call(pc,args,true); 616 else rtn=udf.callWithNamedValues(pc,namedArgs,true); 617 } 618 finally { 619 pc.setVariablesScope(parent); 620 } 621 } 622 } 623 return rtn; 624 } 625 626 /*private void openLock(int id) { 627 // check log 628 if(top.properties._synchronized) { 629 if(top.threadUsingLock!=0 && top.threadUsingLock!=id){ 630 try { 631 top.threadsWaiting++; 632 synchronized(this) { 633 wait(); 634 top.threadsWaiting--; 635 } 636 } catch (InterruptedException e) { 637 638 } 639 } 640 else top.threadUsingLock=id; 641 } 642 } 643 644 private void closeLock() { 645 top.threadUsingLock=0; 646 if(top.threadsWaiting==0)return; 647 synchronized(this) { 648 notify(); 649 } 650 }*/ 651 652 653 /** 654 * will be called before executing method or constructor 655 * @param pc 656 * @return the old scope map 657 */ 658 public Variables beforeCall(PageContext pc) { 659 Variables parent=pc.variablesScope(); 660 pc.setVariablesScope(scope); 661 return parent; 662 } 663 664 /** 665 * will be called after invoking constructor, only invoked by constructor (component body execution) 666 * @param pc 667 * @param parent 668 */ 669 public void afterConstructor(PageContext pc, Variables parent) { 670 pc.setVariablesScope(parent); 671 this.afterConstructor=true; 672 673 if(constructorUDFs!=null){ 674 Iterator<Entry<Key, UDF>> it = constructorUDFs.entrySet().iterator(); 675 Map.Entry<Key, UDF> entry; 676 Key key; 677 UDFImpl udf; 678 while(it.hasNext()){ 679 entry=it.next(); 680 key=entry.getKey(); 681 udf=(UDFImpl) entry.getValue(); 682 registerUDF(key, udf,false,true); 683 } 684 } 685 686 } 687 688 /** 689 * this function may be called by generated code inside a ra file 690 * @deprecated replaced with <code>afterConstructor(PageContext pc, Variables parent)</code> 691 * @param pc 692 * @param parent 693 */ 694 public void afterCall(PageContext pc, Variables parent) { 695 afterConstructor(pc, parent); 696 } 697 698 /** 699 * sets the callpath 700 * @param callPath 701 * / 702 public void setCallPath(String callPath) { 703 properties.callPath=callPath; 704 }*/ 705 706 /** 707 * rerturn the size 708 * @param access 709 * @return size 710 */ 711 public int size(int access) { 712 return keys(access).length; 713 } 714 715 /** 716 * list of keys 717 * @param c 718 * @param access 719 * @param doBase 720 * @return key set 721 */ 722 public Set<Key> keySet(int access) { 723 HashSet<Key> set=new HashSet<Key>(); 724 Map.Entry<Key, Member> entry; 725 Iterator<Entry<Key, Member>> it = _data.entrySet().iterator(); 726 while(it.hasNext()) { 727 entry=it.next(); 728 if(entry.getValue().getAccess()<=access)set.add(entry.getKey()); 729 } 730 return set; 731 } 732 733 /*protected Set<Key> udfKeySet(int access) { 734 Set<Key> set=new HashSet<Key>(); 735 Member m; 736 Map.Entry<Key, UDF> entry; 737 Iterator<Entry<Key, UDF>> it = _udfs.entrySet().iterator(); 738 while(it.hasNext()) { 739 entry= it.next(); 740 m=entry.getValue(); 741 if(m.getAccess()<=access)set.add(entry.getKey()); 742 } 743 return set; 744 }*/ 745 746 747 protected java.util.List<Member> getMembers(int access) { 748 java.util.List<Member> members=new ArrayList<Member>(); 749 Member e; 750 Iterator<Entry<Key, Member>> it = _data.entrySet().iterator(); 751 while(it.hasNext()) { 752 e=it.next().getValue(); 753 if(e.getAccess()<=access)members.add(e); 754 } 755 return members; 756 } 757 758 759 760 /** 761 * return iterator for keys 762 * @param access 763 * @return iterator of the keys 764 */ 765 public Iterator iterator(int access) { 766 return new ArrayIterator(keysAsString(access)); 767 } 768 769 /** 770 * @param access 771 * @return keys inside Component 772 */ 773 public Collection.Key[] keys(int access) { 774 Set<Key> set = keySet(access); 775 return set.toArray(new Collection.Key[set.size()]); 776 } 777 778 /** 779 * @param access 780 * @return 781 */ 782 public String[] keysAsString(int access) { 783 Collection.Key[] keys = keys(access); 784 String[] strKeys = new String[keys.length]; 785 for(int i=0;i<keys.length;i++) { 786 strKeys[i]=keys[i].getString(); 787 } 788 return strKeys; 789 } 790 791 /** 792 * clear all member 793 */ 794 public void clear() { 795 _data.clear(); 796 _udfs.clear(); 797 } 798 799 800 801 public Member getMember(int access,Collection.Key key, boolean dataMember,boolean superAccess) { 802 // check super 803 if(dataMember && access==ACCESS_PRIVATE && key.equalsIgnoreCase(KeyImpl.SUPER)) { 804 return SuperComponent.superMember((ComponentImpl)ComponentUtil.getActiveComponent((PageContextImpl)ThreadLocalPageContext.get(),this)._base()); 805 //return SuperComponent . superMember(base); 806 } 807 if(superAccess) { 808 return (Member) _udfs.get(key); 809 } 810 // check data 811 Member member=(Member)_data.get(key); 812 if(member!=null) { 813 if(member.getAccess()<=access)return member; 814 return null; 815 } 816 return null; 817 } 818 819 820 /** 821 * get entry matching key 822 * @param access 823 * @param keyLowerCase key lower case (case sensitive) 824 * @param doBase do check also base component 825 * @param dataMember do also check if key super 826 * @return matching entry if exists otherwise null 827 */ 828 protected Member getMember(PageContext pc, Collection.Key key, boolean dataMember,boolean superAccess) { 829 // check super 830 if(dataMember && isPrivate(pc) && key.equalsIgnoreCase(KeyImpl.SUPER)) { 831 return SuperComponent.superMember((ComponentImpl)ComponentUtil.getActiveComponent((PageContextImpl)pc,this)._base()); 832 } 833 if(superAccess) 834 return (Member) _udfs.get(key); 835 836 // check data 837 Member member=(Member)_data.get(key); 838 if(isAccessible(pc,member)) return member; 839 return null; 840 } 841 842 private boolean isAccessible(PageContext pc, Member member) { 843 // TODO geschwindigkeit 844 if(member!=null) { 845 int access=member.getAccess(); 846 if(access<=ACCESS_PUBLIC) return true; 847 else if(access==ACCESS_PRIVATE && isPrivate(pc)) return true; 848 else if(access==ACCESS_PACKAGE && isPackage(pc)) return true; 849 /*switch(member.getAccess()) { 850 case ACCESS_REMOTE: return true; 851 case ACCESS_PUBLIC: return true; 852 case ACCESS_PRIVATE: 853 if(isPrivate(pc)) return true; 854 break; 855 case ACCESS_PACKAGE: 856 if(isPackage(pc)) return true; 857 break; 858 }*/ 859 } 860 return false; 861 } 862 863 /** 864 * @param pc 865 * @return returns if is private 866 */ 867 private boolean isPrivate(PageContext pc) { 868 if(pc==null) return true; 869 Component ac = pc.getActiveComponent(); 870 return (ac!=null && (ac==this || 871 ((ComponentImpl)ac).top.pageSource.equals(top.pageSource))) ; 872 } 873 /** 874 * @param pc 875 * @return returns if is package 876 */ 877 private boolean isPackage(PageContext pc) { 878 Component ac = pc.getActiveComponent(); 879 if(ac!=null) { 880 if(ac==this) return true; 881 ComponentImpl aci = ((ComponentImpl)ac); 882 if(aci.top.pageSource.equals(top.pageSource))return true; 883 884 int index; 885 String other=aci.top.getAbsName(); 886 index=other.lastIndexOf('.'); 887 if(index==-1)other=""; 888 else other=other.substring(0,index); 889 890 String my=top.getAbsName(); 891 index=my.lastIndexOf('.'); 892 if(index==-1)my=""; 893 else my=my.substring(0,index); 894 895 return my.equalsIgnoreCase(other); 896 } 897 return false; 898 } 899 900 /** 901 * return the access of a member 902 * @param key 903 * @return returns the access (Component.ACCESS_REMOTE, ACCESS_PUBLIC, ACCESS_PACKAGE,Component.ACCESS_PRIVATE) 904 */ 905 private int getAccess(Collection.Key key){ 906 Member member=getMember(ACCESS_PRIVATE,key,false,false); 907 if(member==null) return Component.ACCESS_PRIVATE; 908 return member.getAccess(); 909 } 910 911 /** 912 * returns current access to this component 913 * @param pc 914 * @return access 915 */ 916 private int getAccess(PageContext pc) { 917 if(pc==null) return ACCESS_PUBLIC; 918 919 if(isPrivate(pc)) return ACCESS_PRIVATE; 920 if(isPackage(pc)) return ACCESS_PACKAGE; 921 return ACCESS_PUBLIC; 922 } 923 924 /** 925 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 926 */ 927 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 928 return toDumpData(pageContext,maxlevel,dp,getAccess(pageContext)); 929 } 930 931 932 /** 933 * to html output print only with access less than given access 934 * @param pageContext 935 * @param access 936 * @return html output 937 */ 938 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp, int access) { 939 DumpTable table = new DumpTablePro("component","#99cc99","#ccffcc","#000000"); 940 table.setTitle("Component "+getCallPath()+""+(" "+StringUtil.escapeHTML(top.properties.dspName))); 941 table.setComment("Only the functions and data members that are accessible from your location are displayed"); 942 if(top.properties.extend.length()>0)table.appendRow(1,new SimpleDumpData("Extends"),new SimpleDumpData(top.properties.extend)); 943 if(top.properties.hint.trim().length()>0)table.appendRow(1,new SimpleDumpData("Hint"),new SimpleDumpData(top.properties.hint)); 944 945 DumpTable content = _toDumpData(top,pageContext,maxlevel,dp,access); 946 if(!content.isEmpty())table.appendRow(1,new SimpleDumpData(""),content); 947 return table; 948 } 949 950 static DumpTable _toDumpData(ComponentImpl ci,PageContext pc, int maxlevel, DumpProperties dp,int access) { 951 maxlevel--; 952 ComponentWrap cw=new ComponentWrap(Component.ACCESS_PRIVATE, ci); 953 Collection.Key[] keys= cw.keys(); 954 955 956 957 DumpTable[] accesses=new DumpTable[4]; 958 accesses[Component.ACCESS_PRIVATE] = new DumpTable("#ff6633","#ff9966","#000000"); 959 accesses[Component.ACCESS_PRIVATE].setTitle("private"); 960 accesses[Component.ACCESS_PRIVATE].setWidth("100%"); 961 //accesses[Component.ACCESS_PRIVATE].setRow(1,"100%"); 962 accesses[Component.ACCESS_PACKAGE] = new DumpTable("#ff9966","#ffcc99","#000000"); 963 accesses[Component.ACCESS_PACKAGE].setTitle("package"); 964 accesses[Component.ACCESS_PACKAGE].setWidth("100%"); 965 accesses[Component.ACCESS_PUBLIC] = new DumpTable("#ffcc99","#ffffcc","#000000"); 966 accesses[Component.ACCESS_PUBLIC].setTitle("public"); 967 accesses[Component.ACCESS_PUBLIC].setWidth("100%"); 968 accesses[Component.ACCESS_REMOTE] = new DumpTable("#ccffcc","#ffffff","#000000"); 969 accesses[Component.ACCESS_REMOTE].setTitle("remote"); 970 accesses[Component.ACCESS_REMOTE].setWidth("100%"); 971 972 Collection.Key key; 973 for(int i=0;i<keys.length;i++) { 974 key=keys[i]; 975 int a=ci.getAccess(key); 976 DumpTable box=accesses[a]; 977 Object o=cw.get(key,null); 978 if(o==ci)o="[this]"; 979 if(DumpUtil.keyValid(dp,maxlevel, key)) 980 box.appendRow(1,new SimpleDumpData(key.getString()),DumpUtil.toDumpData(o,pc,maxlevel,dp)); 981 } 982 983 984 DumpTable table=new DumpTable("#ffffff","#cccccc","#000000"); 985 986 // properties 987 if(ci.top.properties.persistent || ci.top.properties.accessors){ 988 Property[] properties=ci.getProperties(false); 989 DumpTable prop = new DumpTable("#99cc99","#ccffcc","#000000"); 990 991 prop.setTitle("Properties"); 992 prop.setWidth("100%"); 993 Property p; 994 Object child; 995 for(int i=0;i<properties.length;i++) { 996 p=properties[i]; 997 child = ci.scope.get(KeyImpl.init(p.getName()),null); 998 DumpData dd; 999 if(child instanceof Component) { 1000 DumpTable t = new DumpTablePro("component","#99cc99","#ffffff","#000000"); 1001 t.appendRow(1,new SimpleDumpData("Component"),new SimpleDumpData(((Component)child).getCallName())); 1002 dd=t; 1003 1004 } 1005 else 1006 dd=DumpUtil.toDumpData(child, pc, maxlevel-1, dp); 1007 1008 1009 1010 prop.appendRow(1, new SimpleDumpData(p.getName()),dd); 1011 } 1012 1013 if(access>=ACCESS_PUBLIC && !prop.isEmpty()) { 1014 table.appendRow(0,prop); 1015 } 1016 } 1017 1018 1019 1020 1021 if(!accesses[ACCESS_REMOTE].isEmpty()) { 1022 table.appendRow(0,accesses[Component.ACCESS_REMOTE]); 1023 } 1024 if(!accesses[ACCESS_PUBLIC].isEmpty()) { 1025 table.appendRow(0,accesses[Component.ACCESS_PUBLIC]); 1026 } 1027 if(!accesses[ACCESS_PACKAGE].isEmpty()) { 1028 table.appendRow(0,accesses[Component.ACCESS_PACKAGE]); 1029 } 1030 if(!accesses[ACCESS_PRIVATE].isEmpty()) { 1031 table.appendRow(0,accesses[Component.ACCESS_PRIVATE]); 1032 } 1033 return table; 1034 } 1035 1036 /** 1037 * @return return call path 1038 */ 1039 protected String getCallPath() { 1040 if(StringUtil.isEmpty(top.properties.callPath)) return getName(); 1041 try { 1042 return "("+List.arrayToList(List.listToArrayTrim(top.properties.callPath.replace('/','.').replace('\\','.'),"."),".")+")"; 1043 } catch (PageException e) { 1044 return top.properties.callPath; 1045 } 1046 } 1047 1048 /** 1049 * @see railo.runtime.Component#getDisplayName() 1050 */ 1051 public String getDisplayName() { 1052 return top.properties.dspName; 1053 } 1054 1055 /** 1056 * @see railo.runtime.Component#getExtends() 1057 */ 1058 public String getExtends() { 1059 return top.properties.extend; 1060 } 1061 public String getBaseAbsName() { 1062 return top.base.pageSource.getComponentName(); 1063 } 1064 1065 public boolean isBasePeristent() { 1066 return top.base!=null && top.base.properties.persistent; 1067 } 1068 1069 1070 /** 1071 * @see railo.runtime.Component#getHint() 1072 */ 1073 public String getHint() { 1074 return top.properties.hint; 1075 } 1076 1077 // FUTURE add to interface 1078 public String getWSDLFile() { 1079 return top.properties.getWsdlFile(); 1080 } 1081 1082 /** 1083 * @see railo.runtime.Component#getName() 1084 */ 1085 public String getName() { 1086 if(top.properties.callPath==null) return ""; 1087 return List.last(top.properties.callPath,"./",true); 1088 } 1089 public String _getName() { // MUST nicht so toll 1090 if(properties.callPath==null) return ""; 1091 return List.last(properties.callPath,"./",true); 1092 } 1093 public PageSource _getPageSource() { 1094 return pageSource; 1095 } 1096 1097 /** 1098 * @see railo.runtime.Component#getCallName() 1099 */ 1100 public String getCallName() { 1101 return top.properties.callPath; 1102 } 1103 1104 /** 1105 * @see railo.runtime.Component#getAbsName() 1106 */ 1107 public String getAbsName() { 1108 return top.pageSource.getComponentName(); 1109 } 1110 1111 1112 /** 1113 * @see railo.runtime.Component#getOutput() 1114 */ 1115 public boolean getOutput() { 1116 if(top.properties.output==null) return true; 1117 return top.properties.output.booleanValue(); 1118 } 1119 1120 /** 1121 * @see railo.runtime.Component#instanceOf(java.lang.String) 1122 */ 1123 public boolean instanceOf(String type) { 1124 1125 ComponentImpl c=top; 1126 do { 1127 if(type.equalsIgnoreCase(c.properties.callPath)) return true; 1128 if(type.equalsIgnoreCase(c.pageSource.getComponentName())) return true; 1129 if(type.equalsIgnoreCase(c._getName())) return true; 1130 1131 // check interfaces 1132 if(c.interfaceCollection!=null){ 1133 InterfaceImpl[] interfaces = c.interfaceCollection.getInterfaces(); 1134 if(interfaces!=null)for(int i=0;i<interfaces.length;i++){ 1135 if(interfaces[i].instanceOf(type))return true; 1136 } 1137 } 1138 c=c.base; 1139 } 1140 while(c!=null); 1141 if(StringUtil.endsWithIgnoreCase(type, "component")){ 1142 if(type.equalsIgnoreCase("component")) return true; 1143 if(type.equalsIgnoreCase("web-inf.cftags.component")) return true; 1144 //if(type.equalsIgnoreCase("web-inf.railo.context.component")) return true; 1145 1146 } 1147 return false; 1148 } 1149 1150 public boolean equalTo(String type) { 1151 ComponentImpl c=top; 1152 1153 if(type.equalsIgnoreCase(c.properties.callPath)) return true; 1154 if(type.equalsIgnoreCase(c.pageSource.getComponentName())) return true; 1155 if(type.equalsIgnoreCase(c._getName())) return true; 1156 1157 // check interfaces 1158 if(c.interfaceCollection!=null){ 1159 InterfaceImpl[] interfaces = c.interfaceCollection.getInterfaces(); 1160 if(interfaces!=null)for(int i=0;i<interfaces.length;i++){ 1161 if(interfaces[i].instanceOf(type))return true; 1162 } 1163 } 1164 1165 if(StringUtil.endsWithIgnoreCase(type, "component")){ 1166 if(type.equalsIgnoreCase("component")) return true; 1167 if(type.equalsIgnoreCase("web-inf.cftags.component")) return true; 1168 } 1169 return false; 1170 } 1171 1172 1173 /** 1174 * @see railo.runtime.Component#isValidAccess(int) 1175 */ 1176 public boolean isValidAccess(int access) { 1177 return !(access <0 || access>ACCESS_COUNT); 1178 } 1179 1180 /** 1181 * @return returns the ComponentPage of the Component 1182 * @deprecated use instead getPageSource() 1183 */ 1184 public Page getPage() { 1185 throw new PageRuntimeException(new DeprecatedException("method getPage():Page is no longer suppoted, use instead getPageSource():PageSource")); 1186 //return properties.page; 1187 } 1188 1189 1190 1191 // FUTURE add to interface 1192 public PageSource getPageSource() { 1193 return top.pageSource; 1194 } 1195 1196 1197 /** 1198 * @see railo.runtime.op.Castable#castToString() 1199 */ 1200 public String castToString() throws PageException { 1201 return castToString(false); 1202 } 1203 1204 /** 1205 * @see railo.runtime.type.util.StructSupport#castToString(java.lang.String) 1206 */ 1207 public String castToString(String defaultValue) { 1208 return castToString(false,defaultValue); 1209 } 1210 1211 String castToString(boolean superAccess) throws PageException { 1212 // magic function 1213 PageContext pc = ThreadLocalPageContext.get(); 1214 if(pc!=null) { 1215 Member member = getMember(pc,TO_STRING,true,superAccess); 1216 //Object o = get(pc,"_toString",null); 1217 if(member instanceof UDF) { 1218 UDF udf = (UDF)member; 1219 if(udf.getReturnType()==CFTypes.TYPE_STRING && udf.getFunctionArguments().length==0) { 1220 return Caster.toString(_call(pc, udf, null, new Object[0])); 1221 } 1222 } 1223 } 1224 1225 1226 throw ExceptionUtil.addHint(new ExpressionException("Can't cast Component ["+getName()+"] to String"),"Add a User-Defined-Function to Component with the following pattern [_toString():String] to cast it to a String or use Build-In-Function \"serialize(Component):String\" to convert it to a serialized String"); 1227 1228 } 1229 1230 1231 1232 1233 String castToString(boolean superAccess,String defaultValue) { 1234 // magic function 1235 PageContext pc = ThreadLocalPageContext.get(); 1236 if(pc!=null) { 1237 Member member = getMember(pc,TO_STRING,true,superAccess); 1238 //Object o = get(pc,"_toString",null); 1239 if(member instanceof UDF) { 1240 UDF udf = (UDF)member; 1241 if(udf.getReturnType()==CFTypes.TYPE_STRING && udf.getFunctionArguments().length==0) { 1242 try { 1243 return Caster.toString(_call(pc, udf, null, new Object[0]),defaultValue); 1244 } catch (PageException e) { 1245 return defaultValue; 1246 } 1247 } 1248 } 1249 } 1250 return defaultValue; 1251 } 1252 1253 /** 1254 * @see railo.runtime.op.Castable#castToBooleanValue() 1255 */ 1256 public boolean castToBooleanValue() throws PageException { 1257 return castToBooleanValue(false); 1258 } 1259 1260 /** 1261 * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean) 1262 */ 1263 public Boolean castToBoolean(Boolean defaultValue) { 1264 return castToBoolean(false, defaultValue); 1265 } 1266 1267 boolean castToBooleanValue(boolean superAccess) throws PageException { 1268 // magic function 1269 PageContext pc = ThreadLocalPageContext.get(); 1270 if(pc!=null) { 1271 Member member = getMember(pc,TO_BOOLEAN,true,superAccess); 1272 //Object o = get(pc,"_toBoolean",null); 1273 if(member instanceof UDF) { 1274 UDF udf = (UDF)member; 1275 if(udf.getReturnType()==CFTypes.TYPE_BOOLEAN && udf.getFunctionArguments().length==0) { 1276 return Caster.toBooleanValue(_call(pc, udf, null, new Object[0])); 1277 } 1278 } 1279 } 1280 1281 throw ExceptionUtil.addHint(new ExpressionException("Can't cast Component ["+getName()+"] to a boolean value"), 1282 "Add a User-Defined-Function to Component with the following pattern [_toBoolean():boolean] to cast it to a boolean value"); 1283 } 1284 1285 Boolean castToBoolean(boolean superAccess,Boolean defaultValue) { 1286 // magic function 1287 PageContext pc = ThreadLocalPageContext.get(); 1288 if(pc!=null) { 1289 Member member = getMember(pc,TO_BOOLEAN,true,superAccess); 1290 //Object o = get(pc,"_toBoolean",null); 1291 if(member instanceof UDF) { 1292 UDF udf = (UDF)member; 1293 if(udf.getReturnType()==CFTypes.TYPE_BOOLEAN && udf.getFunctionArguments().length==0) { 1294 try { 1295 return Caster.toBoolean(_call(pc, udf, null, new Object[0]),defaultValue); 1296 } catch (PageException e) { 1297 return defaultValue; 1298 } 1299 } 1300 } 1301 } 1302 return defaultValue; 1303 } 1304 1305 /** 1306 * @see railo.runtime.op.Castable#castToDoubleValue() 1307 */ 1308 public double castToDoubleValue() throws PageException { 1309 return castToDoubleValue(false); 1310 } 1311 1312 /** 1313 * @see railo.runtime.op.Castable#castToDoubleValue(double) 1314 */ 1315 public double castToDoubleValue(double defaultValue) { 1316 return castToDoubleValue(false, defaultValue); 1317 } 1318 1319 1320 double castToDoubleValue(boolean superAccess) throws PageException { 1321 // magic function 1322 PageContext pc = ThreadLocalPageContext.get(); 1323 if(pc!=null) { 1324 Member member = getMember(pc,TO_NUMERIC,true,superAccess); 1325 //Object o = get(pc,"_toNumeric",null); 1326 if(member instanceof UDF) { 1327 UDF udf = (UDF)member; 1328 if(udf.getReturnType()==CFTypes.TYPE_NUMERIC && udf.getFunctionArguments().length==0) { 1329 return Caster.toDoubleValue(_call(pc, udf, null, new Object[0])); 1330 } 1331 } 1332 } 1333 1334 throw ExceptionUtil.addHint(new ExpressionException("Can't cast Component ["+getName()+"] to a numeric value"), 1335 "Add a User-Defined-Function to Component with the following pattern [_toNumeric():numeric] to cast it to a numeric value"); 1336 } 1337 double castToDoubleValue(boolean superAccess,double defaultValue) { 1338 // magic function 1339 PageContext pc = ThreadLocalPageContext.get(); 1340 if(pc!=null) { 1341 Member member = getMember(pc,TO_NUMERIC,true,superAccess); 1342 //Object o = get(pc,"_toNumeric",null); 1343 if(member instanceof UDF) { 1344 UDF udf = (UDF)member; 1345 if(udf.getReturnType()==CFTypes.TYPE_NUMERIC && udf.getFunctionArguments().length==0) { 1346 try { 1347 return Caster.toDoubleValue(_call(pc, udf, null, new Object[0]),defaultValue); 1348 } catch (PageException e) { 1349 return defaultValue; 1350 } 1351 } 1352 } 1353 } 1354 return defaultValue; 1355 } 1356 1357 /** 1358 * @see railo.runtime.op.Castable#castToDateTime() 1359 */ 1360 public DateTime castToDateTime() throws PageException { 1361 return castToDateTime(false); 1362 } 1363 1364 /** 1365 * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime) 1366 */ 1367 public DateTime castToDateTime(DateTime defaultValue) { 1368 return castToDateTime(false, defaultValue); 1369 } 1370 1371 DateTime castToDateTime(boolean superAccess) throws PageException { 1372 // magic function 1373 PageContext pc = ThreadLocalPageContext.get(); 1374 if(pc!=null) { 1375 Member member = getMember(pc,TO_DATETIME,true,superAccess); 1376 //Object o = get(pc,"_toDateTime",null); 1377 if(member instanceof UDF) { 1378 UDF udf = (UDF)member; 1379 if(udf.getReturnType()==CFTypes.TYPE_DATETIME && udf.getFunctionArguments().length==0) { 1380 return Caster.toDate(_call(pc, udf, null, new Object[0]),pc.getTimeZone()); 1381 } 1382 } 1383 } 1384 1385 throw ExceptionUtil.addHint(new ExpressionException("Can't cast Component ["+getName()+"] to a date"), 1386 "Add a User-Defined-Function to Component with the following pattern [_toDateTime():datetime] to cast it to a date"); 1387 } 1388 DateTime castToDateTime(boolean superAccess,DateTime defaultValue) { 1389 // magic function 1390 PageContext pc = ThreadLocalPageContext.get(); 1391 if(pc!=null) { 1392 Member member = getMember(pc,TO_DATETIME,true,superAccess); 1393 //Object o = get(pc,"_toDateTime",null); 1394 if(member instanceof UDF) { 1395 UDF udf = (UDF)member; 1396 if(udf.getReturnType()==CFTypes.TYPE_DATETIME && udf.getFunctionArguments().length==0) { 1397 1398 try { 1399 return DateCaster.toDateAdvanced(_call(pc, udf, null, new Object[0]),true,pc.getTimeZone(),defaultValue); 1400 } catch (PageException e) { 1401 return defaultValue; 1402 } 1403 1404 } 1405 } 1406 } 1407 return defaultValue; 1408 } 1409 1410 /** 1411 * @see railo.runtime.Component#getMetaData(railo.runtime.PageContext) 1412 */ 1413 public synchronized Struct getMetaData(PageContext pc) throws PageException { 1414 return getMetaData(ACCESS_PRIVATE,pc,top); 1415 } 1416 1417 1418 public synchronized Object getMetaStructItem(Collection.Key name) { 1419 if(top.properties.meta!=null) { 1420 return top.properties.meta.get(name,null); 1421 } 1422 return null; 1423 } 1424 1425 protected static Struct getMetaData(int access,PageContext pc, ComponentImpl comp) throws PageException { 1426 1427 // Cache 1428 PagePlus page = (PagePlus) ((PageSourceImpl)comp.pageSource).getPage(); 1429 if(page==null) page = (PagePlus) comp.pageSource.loadPage(pc.getConfig()); 1430 if(page.metaData!=null && page.metaData.get()!=null) { 1431 return page.metaData.get(); 1432 } 1433 1434 StructImpl sct=new StructImpl(); 1435 1436 // fill udfs 1437 metaUDFs(pc, comp, sct,access); 1438 1439 // meta 1440 if(comp.properties.meta!=null) 1441 StructUtil.copy(comp.properties.meta, sct, true); 1442 1443 String hint=comp.properties.hint; 1444 String displayname=comp.properties.dspName; 1445 if(!StringUtil.isEmpty(hint))sct.set(KeyImpl.HINT,hint); 1446 if(!StringUtil.isEmpty(displayname))sct.set(DISPLAY_NAME,displayname); 1447 1448 sct.set(PERSISTENT,comp.properties.persistent); 1449 sct.set(ACCESSORS,comp.properties.accessors); 1450 sct.set(SYNCRONIZED,comp.properties._synchronized); 1451 if(comp.properties.output!=null) 1452 sct.set(KeyImpl.OUTPUT,comp.properties.output); 1453 1454 // extends 1455 Struct ex=null; 1456 if(comp.base!=null) ex=getMetaData(access,pc,comp.base); 1457 if(ex!=null)sct.set(EXTENDS,ex); 1458 1459 // implements 1460 InterfaceCollection ic = comp.interfaceCollection; 1461 if(ic!=null){ 1462 Set<String> set = List.listToSet(comp.properties.implement, ",",true); 1463 InterfaceImpl[] interfaces = comp.interfaceCollection.getInterfaces(); 1464 if(!ArrayUtil.isEmpty(interfaces)){ 1465 Struct imp=new StructImpl(); 1466 for(int i=0;i<interfaces.length;i++){ 1467 if(!set.contains(interfaces[i].getCallPath())) continue; 1468 //print.e("-"+interfaces[i].getCallPath()); 1469 imp.setEL(KeyImpl.init(interfaces[i].getCallPath()), interfaces[i].getMetaData(pc)); 1470 } 1471 sct.set(IMPLEMENTS,imp); 1472 } 1473 } 1474 1475 // PageSource 1476 PageSource ps = comp.pageSource; 1477 sct.set(FULLNAME,ps.getComponentName()); 1478 sct.set(KeyImpl.NAME,ps.getComponentName()); 1479 sct.set(KeyImpl.PATH,ps.getDisplayPath()); 1480 sct.set(KeyImpl.TYPE,"component"); 1481 Class skeleton = comp.getJavaAccessClass(new RefBooleanImpl(false),((ConfigImpl)pc.getConfig()).getExecutionLogEnabled(),false,false); 1482 if(skeleton !=null)sct.set(SKELETON, skeleton); 1483 1484 // Properties 1485 if(comp.properties.properties!=null) { 1486 ArrayImpl parr = new ArrayImpl(); 1487 Property p; 1488 Iterator<Entry<String, Property>> pit = comp.properties.properties.entrySet().iterator(); 1489 while(pit.hasNext()){ 1490 p=pit.next().getValue(); 1491 parr.add(p.getMetaData()); 1492 } 1493 parr.sort(new ArrayOfStructComparator(KeyImpl.NAME)); 1494 sct.set(PROPERTIES,parr); 1495 } 1496 page.metaData=new SoftReference<Struct>(sct); 1497 return page.metaData.get(); 1498 } 1499 1500 private static void metaUDFs(PageContext pc,ComponentImpl comp,Struct sct, int access) throws PageException { 1501 ArrayImpl arr=new ArrayImpl(); 1502 //Collection.Key name; 1503 1504 PagePlus page = (PagePlus) ((PageSourceImpl)comp._getPageSource()).getPage(); 1505 if(page!=null && page.udfs!=null){ 1506 for(int i=0;i<page.udfs.length;i++){ 1507 if(page.udfs[i].getAccess()>access) continue; 1508 arr.add(ComponentUtil.getMetaData(pc,page.udfs[i])); 1509 } 1510 } 1511 1512 // property functions 1513 Iterator<Entry<Key, UDF>> it = comp._udfs.entrySet().iterator(); 1514 Entry<Key, UDF> entry; 1515 UDF udf; 1516 while(it.hasNext()) { 1517 entry= it.next(); 1518 udf=entry.getValue(); 1519 if(udf.getAccess()>access || !(udf instanceof UDFGSProperty)) continue; 1520 if(comp.base!=null) { 1521 if(udf==comp.base.getMember(access,entry.getKey(),true,true)) 1522 continue; 1523 } 1524 arr.append(udf.getMetaData(pc)); 1525 1526 } 1527 if(arr.size()!=0)sct.set(FUNCTIONS,arr); 1528 } 1529 1530 1531 1532 1533 /** 1534 * @see railo.runtime.type.Objects#isInitalized() 1535 */ 1536 public boolean isInitalized() { 1537 return isInit; 1538 } 1539 1540 public void setInitalized(boolean isInit) { 1541 this.isInit=isInit;; 1542 } 1543 1544 1545 /** 1546 * sets a value to the current Component, dont to base Component 1547 * @param key 1548 * @param value 1549 * @return value set 1550 */ 1551 private synchronized Object _set(Collection.Key key, Object value) { 1552 //print.out("set:"+key); 1553 if(value instanceof UDFImpl) { 1554 UDFImpl udf = (UDFImpl)((UDF)value).duplicate(); 1555 //udf.isComponentMember(true);///+++ 1556 udf.setOwnerComponent(this); 1557 if(udf.getAccess()>Component.ACCESS_PUBLIC) 1558 udf.setAccess(Component.ACCESS_PUBLIC); 1559 _data.put(key,udf); 1560 _udfs.put(key,udf); 1561 1562 } 1563 else { 1564 _data.put(key,new DataMember(dataMemberDefaultAccess,value)); 1565 } 1566 return value; 1567 } 1568 1569 1570 1571 public void reg(Collection.Key key, UDFImpl udf) { 1572 registerUDF(key, udf,useShadow,false); 1573 } 1574 public void reg(String key, UDFImpl udf) { 1575 registerUDF(KeyImpl.init(key), udf,useShadow,false); 1576 } 1577 1578 public void registerUDF(String key, UDF udf) { 1579 registerUDF(KeyImpl.init(key), (UDFImpl) udf,useShadow,false); 1580 } 1581 public void registerUDF(String key, UDFProperties prop) { 1582 registerUDF(KeyImpl.init(key), new UDFImpl(prop),useShadow,false); 1583 } 1584 1585 public void registerUDF(Collection.Key key, UDF udf) { 1586 registerUDF(key, (UDFImpl) udf,useShadow,false); 1587 } 1588 public void registerUDF(Collection.Key key, UDFProperties prop) { 1589 registerUDF(key, new UDFImpl(prop),useShadow,false); 1590 } 1591 1592 // FUTURE deprecated injected is not used 1593 public void registerUDF(Collection.Key key, UDFImpl udf,boolean useShadow,boolean injected) { 1594 udf.setOwnerComponent(this);//+++ 1595 _udfs.put(key,udf); 1596 _data.put(key,udf); 1597 if(useShadow)scope.setEL(key, udf); 1598 } 1599 1600 /** 1601 * 1602 * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key) 1603 */ 1604 public Object remove(Key key) throws PageException { 1605 return _data.remove(key); 1606 } 1607 1608 public Object removeEL(Collection.Key key) { 1609 // MUST access muss beruecksichtigt werden 1610 return _data.remove(key); 1611 } 1612 1613 /** 1614 * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, java.lang.String, java.lang.Object) 1615 */ 1616 public Object set(PageContext pc, String name, Object value) throws PageException { 1617 return set(pc, KeyImpl.init(name), value); 1618 } 1619 1620 /** 1621 * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 1622 */ 1623 public Object set(PageContext pc, Collection.Key key, Object value) throws PageException { 1624 if(triggerDataMember && isInit) { 1625 if(pc==null)pc=ThreadLocalPageContext.get(); 1626 1627 if(!isPrivate(pc)) { 1628 return callSetter(pc, key, value); 1629 } 1630 } 1631 return _set(key,value); 1632 } 1633 1634 /** 1635 * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object) 1636 */ 1637 public Object set(Collection.Key key, Object value) throws PageException { 1638 return set(null,key,value); 1639 } 1640 1641 /** 1642 * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, java.lang.String, java.lang.Object) 1643 */ 1644 public Object setEL(PageContext pc, String name, Object value) { 1645 try {return set(pc, name, value);} 1646 catch (PageException e) {return null;} 1647 } 1648 1649 /** 1650 * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 1651 */ 1652 public Object setEL(PageContext pc, Collection.Key name, Object value) { 1653 try {return set(pc, name, value);} 1654 catch (PageException e) {return null;} 1655 } 1656 1657 /** 1658 * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object) 1659 */ 1660 public Object setEL(Key key, Object value) { 1661 return setEL(null, key, value); 1662 } 1663 1664 1665 /** 1666 * @see railo.runtime.type.ContextCollection#get(railo.runtime.PageContext, java.lang.String) 1667 */ 1668 public Object get(PageContext pc, String name) throws PageException { 1669 return get(pc, KeyImpl.init(name)); 1670 } 1671 1672 public Object get(PageContext pc, Collection.Key key) throws PageException { 1673 Member member=getMember(pc,key,true,false); 1674 if(member!=null) return member.getValue(); 1675 1676 // trigger 1677 if(triggerDataMember && !isPrivate(pc)) { 1678 return callGetter(pc,key); 1679 } 1680 throw new ExpressionException("Component ["+getCallName()+"] has no accessible Member with name ["+key+"]","enable [trigger data member] in admininistrator to also invoke getters and setters"); 1681 //throw new ExpressionException("Component ["+getCallName()+"] has no accessible Member with name ["+name+"]"); 1682 } 1683 1684 private Object callGetter(PageContext pc,Collection.Key key) throws PageException { 1685 Member member=getMember(pc,KeyImpl.getInstance("get"+key.getLowerString()),false,false); 1686 if(member instanceof UDF) { 1687 UDF udf = (UDF)member; 1688 if(udf.getFunctionArguments().length==0 && udf.getReturnType()!=CFTypes.TYPE_VOID) { 1689 return _call(pc,udf,null,ArrayUtil.OBJECT_EMPTY); 1690 } 1691 } 1692 throw new ExpressionException("Component ["+getCallName()+"] has no accessible Member with name ["+key+"]"); 1693 } 1694 1695 private Object callGetter(PageContext pc,Collection.Key key, Object defaultValue) { 1696 Member member=getMember(pc,KeyImpl.getInstance("get"+key.getLowerString()),false,false); 1697 if(member instanceof UDF) { 1698 UDF udf = (UDF)member; 1699 if(udf.getFunctionArguments().length==0 && udf.getReturnType()!=CFTypes.TYPE_VOID) { 1700 try { 1701 return _call(pc,udf,null,ArrayUtil.OBJECT_EMPTY); 1702 } catch (PageException e) { 1703 return defaultValue; 1704 } 1705 } 1706 } 1707 return defaultValue; 1708 } 1709 1710 private Object callSetter(PageContext pc,Collection.Key key, Object value) throws PageException { 1711 Member member=getMember(pc,KeyImpl.getInstance("set"+key.getLowerString()),false,false); 1712 if(member instanceof UDF) { 1713 UDF udf = (UDF)member; 1714 if(udf.getFunctionArguments().length==1 && (udf.getReturnType()==CFTypes.TYPE_VOID) || udf.getReturnType()==CFTypes.TYPE_ANY ) {// TDOO support int return type 1715 return _call(pc,udf,null,new Object[]{value}); 1716 } 1717 } 1718 return _set(key,value); 1719 } 1720 1721 1722 /** 1723 * return element that has at least given access or null 1724 * @param access 1725 * @param name 1726 * @return matching value 1727 * @throws PageException 1728 */ 1729 public Object get(int access, String name) throws PageException { 1730 return get(access, KeyImpl.init(name)); 1731 } 1732 1733 public Object get(int access, Collection.Key key) throws PageException { 1734 Member member=getMember(access,key,true,false); 1735 if(member!=null) return member.getValue(); 1736 1737 // Trigger 1738 if(triggerDataMember && !isPrivate(ThreadLocalPageContext.get())) { 1739 return callGetter(ThreadLocalPageContext.get(),key); 1740 } 1741 throw new ExpressionException("Component ["+getCallName()+"] has no accessible Member with name ["+key+"]"); 1742 } 1743 1744 /** 1745 * @see railo.runtime.type.ContextCollection#get(railo.runtime.PageContext, java.lang.String, java.lang.Object) 1746 */ 1747 public Object get(PageContext pc, String name, Object defaultValue) { 1748 return get(pc, KeyImpl.init(name), defaultValue); 1749 } 1750 1751 /** 1752 * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object) 1753 */ 1754 public Object get(PageContext pc, Collection.Key key, Object defaultValue) { 1755 Member member=getMember(pc,key,true,false); 1756 if(member!=null) return member.getValue(); 1757 1758 // trigger 1759 if(triggerDataMember && !isPrivate(pc)) { 1760 return callGetter(pc,key,defaultValue); 1761 } 1762 return defaultValue; 1763 } 1764 1765 /** 1766 * return element that has at least given access or null 1767 * @param access 1768 * @param name 1769 * @return matching value 1770 */ 1771 protected Object get(int access, String name, Object defaultValue) { 1772 return get(access, KeyImpl.init(name), defaultValue); 1773 } 1774 1775 /** 1776 * @param access 1777 * @param key 1778 * @param defaultValue 1779 * @return 1780 */ 1781 public Object get(int access, Collection.Key key, Object defaultValue) { 1782 Member member=getMember(access,key,true,false); 1783 if(member!=null) return member.getValue(); 1784 1785 // trigger 1786 if(triggerDataMember && !isPrivate(ThreadLocalPageContext.get())) { 1787 return callGetter(ThreadLocalPageContext.get(),key,defaultValue); 1788 } 1789 return defaultValue; 1790 } 1791 1792 /** 1793 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key) 1794 */ 1795 public Object get(Collection.Key key) throws PageException { 1796 return get(ThreadLocalPageContext.get(),key); 1797 } 1798 1799 /** 1800 * 1801 * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object) 1802 */ 1803 public Object get(Collection.Key key, Object defaultValue) { 1804 return get(ThreadLocalPageContext.get(),key,defaultValue); 1805 } 1806 1807 /** 1808 * @see railo.runtime.Component#call(railo.runtime.PageContext, java.lang.String, java.lang.Object[]) 1809 */ 1810 public Object call(PageContext pc, String name, Object[] args) throws PageException { 1811 return _call(pc,KeyImpl.init(name),null,args,false); 1812 } 1813 1814 public Object call(PageContext pc, Collection.Key name, Object[] args) throws PageException { 1815 return _call(pc,name,null,args,false); 1816 } 1817 1818 protected Object call(PageContext pc, int access, String name, Object[] args) throws PageException { 1819 return _call(pc,access,KeyImpl.init(name),null,args,false); 1820 } 1821 1822 public Object call(PageContext pc, int access, Collection.Key name, Object[] args) throws PageException { 1823 return _call(pc,access,name,null,args,false); 1824 } 1825 1826 /** 1827 * @see railo.runtime.Component#callWithNamedValues(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct) 1828 */ 1829 public Object callWithNamedValues(PageContext pc, String name, Struct args) throws PageException { 1830 return _call(pc,KeyImpl.init(name),args,null,false); 1831 } 1832 1833 public Object callWithNamedValues(PageContext pc, Collection.Key methodName, Struct args) throws PageException { 1834 return _call(pc,methodName,args,null,false); 1835 } 1836 1837 protected Object callWithNamedValues(PageContext pc, int access, String name, Struct args) throws PageException { 1838 return _call(pc,access,KeyImpl.init(name),args,null,false); 1839 } 1840 1841 public Object callWithNamedValues(PageContext pc, int access, Collection.Key name, Struct args) throws PageException { 1842 return _call(pc,access,name,args,null,false); 1843 } 1844 1845 public boolean contains(PageContext pc,String name) { 1846 return get(getAccess(pc),name,null)!=null; 1847 } 1848 1849 /** 1850 * @param pc 1851 * @param key 1852 * @return 1853 */ 1854 public boolean contains(PageContext pc,Key key) { 1855 return get(getAccess(pc),key,null)!=null; 1856 } 1857 1858 /** 1859 * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key) 1860 */ 1861 public boolean containsKey(Key key) { 1862 return contains(ThreadLocalPageContext.get(),key); 1863 } 1864 1865 public boolean contains(int access,String name) { 1866 return get(access,name,null)!=null; 1867 } 1868 1869 public boolean contains(int access,Key name) { 1870 return get(access,name,null)!=null; 1871 } 1872 1873 /** 1874 * @see railo.runtime.type.Collection#keyIterator() 1875 */ 1876 public Iterator keyIterator() { 1877 return iterator(getAccess(ThreadLocalPageContext.get())); 1878 } 1879 1880 /** 1881 * @see railo.runtime.type.Collection#keysAsString() 1882 */ 1883 public String[] keysAsString() { 1884 return keysAsString(getAccess(ThreadLocalPageContext.get())); 1885 } 1886 1887 public Collection.Key[] keys() { 1888 return keys(getAccess(ThreadLocalPageContext.get())); 1889 } 1890 1891 /** 1892 * @see railo.runtime.type.Collection#size() 1893 */ 1894 public int size() { 1895 return size(getAccess(ThreadLocalPageContext.get())); 1896 } 1897 1898 1899 /** 1900 * @param isNew because we can return only one value we give a editable boolean in to 1901 * become tzhe info if the class is new or not 1902 * @return 1903 * @throws PageException 1904 */ 1905 public Class getJavaAccessClass(RefBoolean isNew) throws PageException { 1906 return getJavaAccessClass(isNew, false,true,true); 1907 } 1908 1909 public Class getJavaAccessClass(RefBoolean isNew,boolean writeLog, boolean takeTop, boolean create) throws PageException { 1910 isNew.setValue(false); 1911 ComponentProperties props =(takeTop)?top.properties:properties; 1912 if(props.javaAccessClass==null) { 1913 props.javaAccessClass=ComponentUtil.getComponentJavaAccess(this,isNew,create,writeLog); 1914 } 1915 return props.javaAccessClass; 1916 } 1917 1918 public boolean isPersistent() { 1919 return top.properties.persistent; 1920 } 1921 1922 public boolean isAccessors() { 1923 return top.properties.accessors; 1924 } 1925 1926 public void setProperty(Property property) throws PageException { 1927 top.properties.properties.put(StringUtil.toLowerCase(property.getName()),property); 1928 if(top.properties.persistent || top.properties.accessors){ 1929 if(property.getDefault()!=null)scope.setEL(KeyImpl.init(property.getName()), property.getDefault()); 1930 PropertyFactory.createPropertyUDFs(this,property); 1931 } 1932 } 1933 1934 1935 1936 private void initProperties() throws PageException { 1937 top.properties.properties=new LinkedHashMap<String,Property>(); 1938 1939 // MappedSuperClass 1940 if(isPersistent() && !isBasePeristent() && top.base!=null && top.base.properties.properties!=null && top.base.properties.meta!=null) { 1941 boolean msc = Caster.toBooleanValue(top.base.properties.meta.get(MAPPED_SUPER_CLASS,Boolean.FALSE),false); 1942 if(msc){ 1943 Property p; 1944 Iterator<Entry<String, Property>> it = top.base.properties.properties.entrySet().iterator(); 1945 while(it.hasNext()) { 1946 p = it.next().getValue(); 1947 if(p.isPeristent()) { 1948 1949 setProperty(p); 1950 } 1951 } 1952 } 1953 } 1954 } 1955 1956 // FUTURE add to interface and then search for #321 and change this as well 1957 public Property[] getProperties(boolean onlyPeristent) { 1958 if(top.properties.properties==null) return new Property[0]; 1959 1960 1961 // for faster execution we have this 1962 if(!onlyPeristent) { 1963 int index=0; 1964 Iterator<Entry<String, Property>> it = top.properties.properties.entrySet().iterator(); 1965 Property[] props=new Property[top.properties.properties.size()]; 1966 while(it.hasNext()) { 1967 props[index++]=it.next().getValue(); 1968 } 1969 } 1970 1971 1972 // collect with filter 1973 Property p; 1974 java.util.List<Property> props=new ArrayList<Property>(); 1975 Iterator<Entry<String, Property>> it = top.properties.properties.entrySet().iterator(); 1976 while(it.hasNext()) { 1977 p = it.next().getValue(); 1978 if(p.isPeristent()) { 1979 props.add(p); 1980 } 1981 } 1982 1983 return props.toArray(new Property[props.size()]); 1984 } 1985 1986 public ComponentScope getComponentScope() { 1987 return scope; 1988 } 1989 1990 1991 /** 1992 * @see railo.runtime.op.Castable#compare(boolean) 1993 */ 1994 public int compareTo(boolean b) throws PageException { 1995 return Operator.compare(castToBooleanValue(), b); 1996 } 1997 1998 /** 1999 * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime) 2000 */ 2001 public int compareTo(DateTime dt) throws PageException { 2002 return Operator.compare((Date)castToDateTime(), (Date)dt); 2003 } 2004 2005 /** 2006 * @see railo.runtime.op.Castable#compareTo(double) 2007 */ 2008 public int compareTo(double d) throws PageException { 2009 return Operator.compare(castToDoubleValue(), d); 2010 } 2011 2012 /** 2013 * @see railo.runtime.op.Castable#compareTo(java.lang.String) 2014 */ 2015 public int compareTo(String str) throws PageException { 2016 return Operator.compare(castToString(), str); 2017 } 2018 2019 public void addConstructorUDF(Key key, UDF value) { 2020 if(constructorUDFs==null) 2021 constructorUDFs=new HashMap<Key,UDF>(); 2022 constructorUDFs.put(key, (UDF) value); 2023 } 2024 2025 // MUST more native impl 2026 public void readExternal(ObjectInput in) throws IOException,ClassNotFoundException { 2027 boolean pcCreated=false; 2028 PageContext pc = ThreadLocalPageContext.get(); 2029 // MUST this is just a workaround 2030 if(pc==null){ 2031 pcCreated=true; 2032 ConfigWeb config = (ConfigWeb) ThreadLocalPageContext.getConfig(); 2033 Pair[] parr = new Pair[0]; 2034 pc=ThreadUtil.createPageContext(config, DevNullOutputStream.DEV_NULL_OUTPUT_STREAM, "localhost", "/","", new Cookie[0], parr, parr, new StructImpl()); 2035 } 2036 2037 try { 2038 // MUST do serialisation more like the cloning way 2039 ComponentImpl other=(ComponentImpl) new CFMLExpressionInterpreter().interpret(pc,in.readUTF()); 2040 2041 2042 this._data=other._data; 2043 this._udfs=other._udfs; 2044 setOwner(_udfs); 2045 setOwner(_data); 2046 this.afterConstructor=other.afterConstructor; 2047 this.base=other.base; 2048 //this.componentPage=other.componentPage; 2049 this.pageSource=other.pageSource; 2050 this.constructorUDFs=other.constructorUDFs; 2051 this.dataMemberDefaultAccess=other.dataMemberDefaultAccess; 2052 this.interfaceCollection=other.interfaceCollection; 2053 this.isInit=other.isInit; 2054 this.properties=other.properties; 2055 this.scope=other.scope; 2056 this.top=this; 2057 this.triggerDataMember=other.triggerDataMember; 2058 this.useShadow=other.useShadow; 2059 2060 2061 } catch (PageException e) { 2062 throw new IOException(e.getMessage()); 2063 } 2064 finally { 2065 if(pcCreated)ThreadLocalPageContext.release(); 2066 } 2067 } 2068 2069 private void setOwner(Map<Key,? extends Member> data) { 2070 Member m; 2071 Iterator<? extends Member> it = data.values().iterator(); 2072 while(it.hasNext()){ 2073 m=it.next(); 2074 if(m instanceof UDFImpl) { 2075 ((UDFImpl)m).setOwnerComponent(this); 2076 } 2077 } 2078 } 2079 2080 public void writeExternal(ObjectOutput out) throws IOException { 2081 try { 2082 out.writeUTF(new ScriptConverter().serialize(this)); 2083 } 2084 catch (Throwable t) { 2085 //print.printST(t); 2086 } 2087 2088 } 2089 2090 /** 2091 * @see railo.runtime.type.cfc.ComponentAccess#_base() 2092 */ 2093 public ComponentAccess _base() { 2094 return base; 2095 } 2096 }