001    package railo.runtime.tag;
002    
003    import java.io.IOException;
004    import java.util.Iterator;
005    import java.util.Map.Entry;
006    
007    import javax.servlet.jsp.JspWriter;
008    import javax.servlet.jsp.tagext.Tag;
009    
010    import railo.commons.lang.StringUtil;
011    import railo.runtime.Component;
012    import railo.runtime.PageContext;
013    import railo.runtime.PageContextImpl;
014    import railo.runtime.PageSource;
015    import railo.runtime.component.ComponentLoader;
016    import railo.runtime.component.Member;
017    import railo.runtime.customtag.CustomTagUtil;
018    import railo.runtime.customtag.InitFile;
019    import railo.runtime.engine.ThreadLocalPageContext;
020    import railo.runtime.exp.ApplicationException;
021    import railo.runtime.exp.CasterException;
022    import railo.runtime.exp.ExpressionException;
023    import railo.runtime.exp.PageException;
024    import railo.runtime.exp.PageRuntimeException;
025    import railo.runtime.exp.PageServletException;
026    import railo.runtime.ext.tag.AppendixTag;
027    import railo.runtime.ext.tag.BodyTagTryCatchFinallyImpl;
028    import railo.runtime.ext.tag.DynamicAttributes;
029    import railo.runtime.op.Caster;
030    import railo.runtime.op.Decision;
031    import railo.runtime.type.Collection;
032    import railo.runtime.type.Collection.Key;
033    import railo.runtime.type.KeyImpl;
034    import railo.runtime.type.Struct;
035    import railo.runtime.type.StructImpl;
036    import railo.runtime.type.scope.Caller;
037    import railo.runtime.type.scope.CallerImpl;
038    import railo.runtime.type.scope.Undefined;
039    import railo.runtime.type.scope.Variables;
040    import railo.runtime.type.scope.VariablesImpl;
041    import railo.runtime.type.util.ArrayUtil;
042    import railo.runtime.type.util.ComponentUtil;
043    import railo.runtime.type.util.KeyConstants;
044    import railo.runtime.type.util.ListUtil;
045    import railo.runtime.type.util.Type;
046    import railo.runtime.util.QueryStack;
047    import railo.runtime.util.QueryStackImpl;
048    import railo.transformer.library.tag.TagLibTag;
049    import railo.transformer.library.tag.TagLibTagAttr;
050    
051    
052    /**
053    * Creates a CFML Custom Tag
054    **/
055    public class CFTag extends BodyTagTryCatchFinallyImpl implements DynamicAttributes,AppendixTag {
056    
057            private static Collection.Key GENERATED_CONTENT=KeyImpl.intern("GENERATEDCONTENT");
058            private static Collection.Key EXECUTION_MODE=KeyImpl.intern("EXECUTIONMODE");      
059            private static Collection.Key EXECUTE_BODY=KeyImpl.intern("EXECUTEBODY");
060            private static Collection.Key PARENT=KeyImpl.intern("PARENT");
061            private static Collection.Key CFCATCH=KeyConstants._CFCATCH;
062            private static Collection.Key SOURCE=KeyImpl.intern("SOURCE");
063            
064            private static final Collection.Key ON_ERROR = KeyImpl.intern("onError");
065            private static final Collection.Key ON_FINALLY = KeyImpl.intern("onFinally");
066            private static final Collection.Key ON_START_TAG = KeyImpl.intern("onStartTag");
067            private static final Collection.Key ON_END_TAG = KeyImpl.intern("onEndTag");
068    
069            private static final Collection.Key ATTRIBUTE_TYPE = KeyImpl.intern("attributetype");
070            private static final Collection.Key RT_EXPR_VALUE = KeyImpl.intern("rtexprvalue");
071            private static final String MARKER = "2w12801";
072            
073        /**
074         * Field <code>attributesScope</code>
075         */
076        // new scopes
077        protected StructImpl attributesScope;
078        private Caller callerScope;
079        private StructImpl thistagScope;
080    
081        private Variables ctVariablesScope;
082    
083        private boolean hasBody;
084    
085        /**
086         * Field <code>filename</code>
087         */
088        //protected String filename;
089    
090        /**
091         * Field <code>source</code>
092         */
093        protected InitFile source;
094        private String appendix;
095            //private boolean doCustomTagDeepSearch;
096            
097            private Component cfc;
098            private boolean isEndTag;
099            
100            
101            
102        /**
103        * constructor for the tag class
104        **/
105        public CFTag() {
106            attributesScope = new StructImpl();
107            callerScope = new CallerImpl();
108            //thistagScope = new StructImpl();
109        }
110    
111        @Override
112        public void setDynamicAttribute(String uri, String name, Object value) {
113            TagUtil.setDynamicAttribute(attributesScope,KeyImpl.init(name),value,TagUtil.ORIGINAL_CASE);
114        }
115    
116        @Override
117        public void setDynamicAttribute(String uri, Collection.Key name, Object value) {
118            TagUtil.setDynamicAttribute(attributesScope,name,value,TagUtil.ORIGINAL_CASE);
119        }
120    
121        @Override
122        public void release()   {
123            super.release();
124    
125            hasBody=false;
126            //filename=null;      
127    
128            attributesScope=new StructImpl();//.clear();
129            callerScope = new CallerImpl();
130            if(thistagScope!=null)thistagScope=null;
131            if(ctVariablesScope!=null)ctVariablesScope=null;  
132            
133    
134            isEndTag=false;     
135            
136            //cfc=null;
137            source=null;
138        }
139    
140        /**
141         * sets the appendix of the class
142         * @param appendix
143         */
144        public void setAppendix(String appendix) {
145            this.appendix=appendix;
146            //filename = appendix+'.'+pageContext.getConfig().getCFMLExtension();
147        }
148    
149        @Override
150        public int doStartTag() throws PageException    {
151            PageContextImpl pci=(PageContextImpl) pageContext;
152                    boolean old=pci.useSpecialMappings(true);
153                    try{
154                            initFile();
155                    callerScope.initialize(pageContext);
156                    if(source.isCFC())return cfcStartTag();
157                    return cfmlStartTag();  
158                    }
159                    finally{
160                            pci.useSpecialMappings(old);
161                    }
162        }
163    
164        @Override
165        public int doEndTag()   {
166            PageContextImpl pci=(PageContextImpl) pageContext;
167                    boolean old=pci.useSpecialMappings(true);
168                    try{
169                            if(source.isCFC())_doCFCFinally();
170                    return EVAL_PAGE;
171                    }
172                    finally{
173                            pci.useSpecialMappings(old);
174                    }
175        }
176    
177        @Override
178        public void doInitBody()    {
179            
180        }
181    
182        @Override
183        public int doAfterBody() throws PageException   {
184            if(source.isCFC())return cfcEndTag();
185            return cfmlEndTag();
186        }
187        
188    
189            @Override
190        public void doCatch(Throwable t) throws Throwable {
191            if(source.isCFC()){
192                    String source=isEndTag?"end":"body";
193                    isEndTag=false;
194                    _doCFCCatch(t,source);
195            }
196            else super.doCatch(t);
197            }
198        
199        void initFile() throws PageException {
200            source=initFile(pageContext);
201        }
202    
203        public InitFile initFile(PageContext pageContext) throws PageException {
204            return CustomTagUtil.loadInitFile(pageContext, appendix);
205        }
206        
207            private int cfmlStartTag() throws PageException {
208                    callerScope.initialize(pageContext);
209            
210                    // thistag
211                    if(thistagScope==null)thistagScope=new StructImpl(StructImpl.TYPE_LINKED);
212            thistagScope.set(GENERATED_CONTENT,"");
213            thistagScope.set(EXECUTION_MODE,"start");      
214            thistagScope.set(EXECUTE_BODY,Boolean.TRUE);
215            thistagScope.set(KeyConstants._HASENDTAG,Caster.toBoolean(hasBody));
216            
217                    
218                    ctVariablesScope=new VariablesImpl();
219            ctVariablesScope.setEL(KeyConstants._ATTRIBUTES,attributesScope);
220            ctVariablesScope.setEL(KeyConstants._CALLER,callerScope);
221            ctVariablesScope.setEL(KeyConstants._THISTAG,thistagScope);
222            
223            
224            // include
225            doInclude();
226            
227            return Caster.toBooleanValue(thistagScope.get(EXECUTE_BODY))?EVAL_BODY_BUFFERED:SKIP_BODY;
228        } 
229            
230        private int cfmlEndTag() throws PageException {
231            // thistag     
232            String genConBefore = bodyContent.getString();
233            thistagScope.set(GENERATED_CONTENT,genConBefore);
234            thistagScope.set(EXECUTION_MODE,"end");
235            thistagScope.set(EXECUTE_BODY,Boolean.FALSE);
236            writeEL(bodyContent, MARKER);
237            
238            // include
239            try{
240                    doInclude();
241            }
242            catch(Throwable t){
243                    writeOut(genConBefore);
244                    throw Caster.toPageException(t);
245            }
246            
247            writeOut(genConBefore);
248    
249            return Caster.toBooleanValue(thistagScope.get(EXECUTE_BODY))?EVAL_BODY_BUFFERED:SKIP_BODY;
250        }
251    
252        
253    
254            private void writeOut(String genConBefore) throws PageException {
255                    String output = bodyContent.getString(); 
256                    bodyContent.clearBody();
257            String genConAfter = Caster.toString(thistagScope.get(GENERATED_CONTENT));
258            
259            if(genConBefore!=genConAfter){
260                    if(output.startsWith(genConBefore+MARKER)){
261                            output=output.substring((genConBefore+MARKER).length());
262                    }
263                    output=genConAfter+output;
264            }
265            else {
266                    if(output.startsWith(genConBefore+MARKER)){
267                            output=output.substring((genConBefore+MARKER).length());
268                            output=genConBefore+output;
269                    }
270            }
271            
272            
273            writeEL(bodyContent.getEnclosingWriter(),output);
274            }
275    
276            private void writeEL(JspWriter writer, String str) throws PageException {
277                    try {
278                            writer.write(str);
279                    } catch (IOException e) {
280                            throw Caster.toPageException(e);
281                    }
282            }
283    
284            void doInclude() throws PageException {
285            Variables var=pageContext.variablesScope();
286            pageContext.setVariablesScope(ctVariablesScope);
287            
288            
289            QueryStack cs=null;
290            Undefined undefined=pageContext.undefinedScope();
291            int oldMode=undefined.setMode(Undefined.MODE_NO_LOCAL_AND_ARGUMENTS);
292            if(oldMode!=Undefined.MODE_NO_LOCAL_AND_ARGUMENTS)
293                    callerScope.setScope(var,pageContext.localScope(),pageContext.argumentsScope(),true);
294            else 
295                    callerScope.setScope(var,null,null,false);
296            
297            if(pageContext.getConfig().allowImplicidQueryCall()) {
298                cs=undefined.getQueryStack();
299                undefined.setQueryStack(new QueryStackImpl());
300            }
301                
302            try {
303                pageContext.doInclude(new PageSource[]{source.getPageSource()},false);
304            }
305            catch (Throwable t) {
306                throw Caster.toPageException(t);
307            }
308            finally {
309                undefined.setMode(oldMode);
310                //varScopeData=variablesScope.getMap();
311                pageContext.setVariablesScope(var);
312                if(pageContext.getConfig().allowImplicidQueryCall()) {
313                    undefined.setQueryStack(cs);
314                }
315            }
316        
317        }
318        
319        
320        // CFC
321        
322        private int cfcStartTag() throws PageException {
323            
324            callerScope.initialize(pageContext);
325            cfc = ComponentLoader.loadComponent(pageContext,null,source.getPageSource(), source.getFilename().substring(0,source.getFilename().length()-(pageContext.getConfig().getCFCExtension().length()+1)), false,true);
326            validateAttributes(cfc,attributesScope,StringUtil.ucFirst(ListUtil.last(source.getPageSource().getComponentName(),'.')));
327            
328            boolean exeBody = false;
329            try     {
330                            Object rtn=Boolean.TRUE;
331                            if(cfc.contains(pageContext, KeyConstants._init)){
332                            Tag parent=getParent();
333                            while(parent!=null && !(parent instanceof CFTag && ((CFTag)parent).isCFCBasedCustomTag())) {
334                                    parent=parent.getParent();
335                            }
336                                    Struct args=new StructImpl(StructImpl.TYPE_LINKED);
337                                    args.set(KeyConstants._HASENDTAG, Caster.toBoolean(hasBody));
338                            if(parent instanceof CFTag) {
339                                    args.set(PARENT, ((CFTag)parent).getComponent());
340                            }
341                            rtn=cfc.callWithNamedValues(pageContext, KeyConstants._init, args);
342                    }
343                            
344                    if(cfc.contains(pageContext, ON_START_TAG)){
345                            Struct args=new StructImpl();
346                            args.set(KeyConstants._ATTRIBUTES, attributesScope);
347                            setCaller(pageContext,args);
348                            
349                            rtn=cfc.callWithNamedValues(pageContext, ON_START_TAG, args);   
350                        }
351                    exeBody=Caster.toBooleanValue(rtn,true);
352            }
353            catch(Throwable t){
354                    _doCFCCatch(t,"start");
355            }
356            return exeBody?EVAL_BODY_BUFFERED:SKIP_BODY;
357        }
358        
359        private void setCaller(PageContext pageContext, Struct args) throws PageException {
360            callerScope.initialize(pageContext);
361            boolean checkAgs=pageContext.undefinedScope().getCheckArguments();
362            if(checkAgs)
363                    callerScope.setScope(pageContext.variablesScope(),pageContext.localScope(),pageContext.argumentsScope(),true);
364            else 
365                    callerScope.setScope(pageContext.variablesScope(),null,null,false);
366            
367            
368            args.set(KeyConstants._CALLER, callerScope);
369            
370            
371            
372            //args.set(KeyConstants._CALLER, Duplicator.duplicate(pageContext.undefinedScope(),false));
373            }
374    
375            private static void validateAttributes(Component cfc,StructImpl attributesScope,String tagName) throws ApplicationException, ExpressionException {
376                    
377                    TagLibTag tag=getAttributeRequirments(cfc,false);
378                    if(tag==null) return;
379                    
380                    if(tag.getAttributeType()==TagLibTag.ATTRIBUTE_TYPE_FIXED || tag.getAttributeType()==TagLibTag.ATTRIBUTE_TYPE_MIXED){
381                            Iterator<Entry<String, TagLibTagAttr>> it = tag.getAttributes().entrySet().iterator();
382                            int count=0;
383                            Collection.Key key;
384                            TagLibTagAttr attr;
385                            Object value;
386                            Entry<String, TagLibTagAttr> entry;
387                            // check existing attributes
388                            while(it.hasNext()){
389                                    entry = it.next();
390                                    count++;
391                                    key=KeyImpl.toKey(entry.getKey(),null);
392                                    attr=entry.getValue();
393                                    value=attributesScope.get(key,null);
394                                    if(value==null){
395                                            if(attr.getDefaultValue()!=null){
396                                                    value=attr.getDefaultValue();
397                                                    attributesScope.setEL(key, value);
398                                            }
399                                            else if(attr.isRequired())
400                                                    throw new ApplicationException("attribute ["+key.getString()+"] is required for tag ["+tagName+"]");
401                                    }
402                                    if(value!=null) {
403                                            if(!Decision.isCastableTo(attr.getType(),value,true,true,-1)) 
404                                                    throw new CasterException(createMessage(attr.getType(), value));
405                                    
406                                    }
407                            }
408                            
409                            // check if there are attributes not supported
410                            if(tag.getAttributeType()==TagLibTag.ATTRIBUTE_TYPE_FIXED && count<attributesScope.size()){
411                                    Collection.Key[] keys = attributesScope.keys();
412                                    for(int i=0;i<keys.length;i++){
413                                            if(tag.getAttribute(keys[i].getLowerString())==null)
414                                                    throw new ApplicationException("attribute ["+keys[i].getString()+"] is not supported for tag ["+tagName+"]");
415                                    }
416                                    
417                                    //Attribute susi is not allowed for tag cfmail
418                            }
419                    }
420            }
421        
422        private static String createMessage(String type, Object value) {
423            if(value instanceof String) return "can't cast String ["+value+"] to a value of type ["+type+"]";
424            else if(value!=null) return "can't cast Object type ["+Type.getName(value)+"] to a value of type ["+type+"]";
425                    else return "can't cast Null value to value of type ["+type+"]";
426    
427        } 
428        
429    
430            private static TagLibTag getAttributeRequirments(Component cfc, boolean runtime) throws ExpressionException {
431                    
432                    Struct meta=null;
433            //try {
434                    //meta = Caster.toStruct(cfc.get(Component.ACCESS_PRIVATE, METADATA),null,false);
435                    Member mem = ComponentUtil.toComponentAccess(cfc).getMember(Component.ACCESS_PRIVATE, KeyConstants._metadata,true,false);
436                    if(mem!=null)meta = Caster.toStruct(mem.getValue(),null,false);
437                    //}catch (PageException e) {e.printStackTrace();}
438            if(meta==null) return null;
439            
440            TagLibTag tag=new TagLibTag(null);
441        // TAG
442    
443            // type         
444            String type=Caster.toString(meta.get(ATTRIBUTE_TYPE,"dynamic"),"dynamic");
445            
446            if("fixed".equalsIgnoreCase(type))tag.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_FIXED);
447            //else if("mixed".equalsIgnoreCase(type))tag.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_MIXED);
448            //else if("noname".equalsIgnoreCase(type))tag.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_NONAME);
449            else tag.setAttributeType(TagLibTag.ATTRIBUTE_TYPE_DYNAMIC);
450            
451            if(!runtime){
452                    // hint
453                    String hint=Caster.toString(meta.get(KeyConstants._hint,null),null);
454                    if(!StringUtil.isEmpty(hint))tag.setDescription(hint);
455            }
456            
457        // ATTRIBUTES
458            Struct attributes=Caster.toStruct(meta.get(KeyConstants._ATTRIBUTES,null),null,false);
459            if(attributes!=null) {
460                    Iterator<Entry<Key, Object>> it = attributes.entryIterator();
461                    //Iterator it = attributes.entrySet().iterator();
462                    Entry<Key, Object> entry;
463                    TagLibTagAttr attr;
464                    Struct sct;
465                    String name;
466                    Object defaultValue;
467                    while(it.hasNext()){
468                            entry=it.next();
469                            name=Caster.toString(entry.getKey(),null);
470                            if(StringUtil.isEmpty(name)) continue;
471                            attr=new TagLibTagAttr(tag);
472                            attr.setName(name);
473                            
474                            sct=Caster.toStruct(entry.getValue(),null,false);
475                            if(sct!=null){
476                                    attr.setRequired(Caster.toBooleanValue(sct.get(KeyConstants._required,Boolean.FALSE),false));
477                                    attr.setType(Caster.toString(sct.get(KeyConstants._type,"any"),"any"));
478                                    
479                                    defaultValue= sct.get(KeyConstants._default,null);
480                                    if(defaultValue!=null)attr.setDefaultValue(defaultValue);
481                                    
482                                    
483                                    if(!runtime){
484                                            attr.setDescription(Caster.toString(sct.get(KeyConstants._hint,null),null));
485                                            attr.setRtexpr(Caster.toBooleanValue(sct.get(RT_EXPR_VALUE,Boolean.TRUE),true));
486                                    }
487                            }
488                            tag.setAttribute(attr);
489                            
490                    }
491            }
492            return tag;
493            }
494    
495            private int cfcEndTag() throws PageException {
496            
497            boolean exeAgain = false;
498            try{
499                    String output=null;
500                    Object rtn=Boolean.FALSE;
501                    
502                    
503                    if(cfc.contains(pageContext, ON_END_TAG)){
504                            try {
505                                    output=bodyContent.getString();
506                                bodyContent.clearBody();
507                                //rtn=cfc.call(pageContext, ON_END_TAG, new Object[]{attributesScope,pageContext.variablesScope(),output});
508                                
509                                Struct args=new StructImpl(StructImpl.TYPE_LINKED);
510                                    args.set(KeyConstants._ATTRIBUTES, attributesScope);
511                                    setCaller(pageContext, args);
512                                    args.set(GENERATED_CONTENT, output);
513                                    rtn=cfc.callWithNamedValues(pageContext, ON_END_TAG, args);     
514                                
515                                
516                                
517                            }
518                            finally {
519                                    writeEnclosingWriter();
520                            }
521                    }
522                    else writeEnclosingWriter();
523                    
524                    exeAgain= Caster.toBooleanValue(rtn,false);
525                }
526            catch(Throwable t){
527                    isEndTag=true;
528                    throw Caster.toPageException(t);
529            }
530            return exeAgain?EVAL_BODY_BUFFERED:SKIP_BODY;
531            
532        }
533        
534        public void _doCFCCatch(Throwable t, String source) throws PageException {
535            writeEnclosingWriter();
536            
537            // remove PageServletException wrap
538            if(t instanceof PageServletException) {
539                        PageServletException pse=(PageServletException)t;
540                        t=pse.getPageException();
541                    }
542            
543            // abort 
544            try {
545                            if(railo.runtime.exp.Abort.isAbort(t)){
546                                    if(bodyContent!=null){
547                                            bodyContent.writeOut(bodyContent.getEnclosingWriter());
548                                            bodyContent.clearBuffer();
549                                    }
550                                    throw Caster.toPageException(t);
551                            }
552                    }
553                    catch(IOException ioe){
554                            throw Caster.toPageException(ioe);
555                    }
556            
557            
558            
559            try {
560                            if(cfc.contains(pageContext, ON_ERROR)){
561                            PageException pe = Caster.toPageException(t);
562                            //Object rtn=cfc.call(pageContext, ON_ERROR, new Object[]{pe.getCatchBlock(pageContext),source});
563                            
564                            Struct args=new StructImpl(StructImpl.TYPE_LINKED);
565                            args.set(CFCATCH, pe.getCatchBlock(ThreadLocalPageContext.getConfig(pageContext)));
566                            args.set(SOURCE, source);
567                            Object rtn=cfc.callWithNamedValues(pageContext, ON_ERROR, args);        
568                        
569                            if(Caster.toBooleanValue(rtn,false))
570                                            throw t;
571                    }
572                            else throw t;
573            }
574            catch(Throwable th) {
575                    writeEnclosingWriter();
576                    _doCFCFinally();
577                    throw Caster.toPageException(th);
578            }
579            writeEnclosingWriter();
580            }
581        
582        private void _doCFCFinally() {
583                    if(cfc.contains(pageContext, ON_FINALLY)){
584                            try {
585                                    cfc.call(pageContext, ON_FINALLY, ArrayUtil.OBJECT_EMPTY);
586                            } 
587                            catch (PageException pe) {
588                                    throw new PageRuntimeException(pe);
589                            }
590                            finally{
591                                    writeEnclosingWriter();
592                            }
593            }
594            }
595        
596        
597        private void writeEnclosingWriter()  {
598            if(bodyContent!=null){
599                            try {
600                                    String output = bodyContent.getString(); 
601                                    bodyContent.clearBody();
602                        bodyContent.getEnclosingWriter().write(output);    
603                    } 
604                            catch (IOException e) {
605                            //throw Caster.toPageException(e);
606                    }
607            }
608            }
609        
610        
611    
612        /**
613         * sets if tag has a body or not
614         * @param hasBody
615         */
616        public void hasBody(boolean hasBody) {
617            this.hasBody=hasBody;
618        }
619    
620        /**
621         * @return Returns the appendix.
622         */
623        public String getAppendix() {
624            return appendix;
625        }
626    
627        /**
628         * @return return thistag
629         */
630        public Struct getThis() {
631            if(isCFCBasedCustomTag()){
632                    return cfc;
633            }
634            return thistagScope;
635        }
636        
637        /**
638         * @return return thistag
639         */
640        public Struct getCallerScope() {
641            return callerScope;
642        }
643        
644        /**
645         * @return return thistag
646         */
647        public Struct getAttributesScope() {
648            return attributesScope;
649        }
650    
651            /**
652             * @return the ctVariablesScope
653             */
654            public Struct getVariablesScope() {
655                    if(isCFCBasedCustomTag())       {
656                            return cfc.getComponentScope();
657                    }
658                    return ctVariablesScope;
659            }
660            
661        /**
662             * @return the cfc
663             */
664            public Component getComponent() {
665                    return cfc;
666            }
667            
668            public boolean isCFCBasedCustomTag() {
669                    return getSource().isCFC();
670            }
671            
672            private InitFile getSource() {
673                    if(source==null){
674                            try {
675                                    source=initFile(pageContext);
676                            } catch (PageException e) {
677                                    e.printStackTrace();
678                            }
679                    }
680                    return source;
681            }
682    
683            /*class InitFile {
684                    PageSource ps;
685                    String filename;
686                    boolean isCFC;
687    
688                    public InitFile(PageSource ps,String filename,boolean isCFC){
689                            this.ps=ps;
690                            this.filename=filename;
691                            this.isCFC=isCFC;
692                    }
693            }*/
694            
695            
696    }