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