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