001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime;
020
021
022import java.io.IOException;
023import java.io.OutputStream;
024import java.nio.charset.Charset;
025import java.sql.Statement;
026import java.util.ArrayList;
027import java.util.Date;
028import java.util.Enumeration;
029import java.util.HashSet;
030import java.util.LinkedList;
031import java.util.List;
032import java.util.Locale;
033import java.util.Map;
034import java.util.Map.Entry;
035import java.util.Set;
036import java.util.Stack;
037import java.util.TimeZone;
038import java.util.concurrent.ConcurrentHashMap;
039
040import javax.servlet.Servlet;
041import javax.servlet.ServletConfig;
042import javax.servlet.ServletContext;
043import javax.servlet.ServletException;
044import javax.servlet.ServletRequest;
045import javax.servlet.ServletResponse;
046import javax.servlet.http.HttpServlet;
047import javax.servlet.http.HttpServletRequest;
048import javax.servlet.http.HttpServletResponse;
049import javax.servlet.http.HttpSession;
050import javax.servlet.jsp.JspException;
051import javax.servlet.jsp.JspWriter;
052import javax.servlet.jsp.tagext.BodyContent;
053import javax.servlet.jsp.tagext.BodyTag;
054import javax.servlet.jsp.tagext.Tag;
055import javax.servlet.jsp.tagext.TryCatchFinally;
056
057import lucee.commons.db.DBUtil;
058import lucee.commons.io.BodyContentStack;
059import lucee.commons.io.CharsetUtil;
060import lucee.commons.io.IOUtil;
061import lucee.commons.io.res.Resource;
062import lucee.commons.io.res.util.ResourceClassLoader;
063import lucee.commons.lang.ExceptionUtil;
064import lucee.commons.lang.PhysicalClassLoader;
065import lucee.commons.lang.SizeOf;
066import lucee.commons.lang.StringUtil;
067import lucee.commons.lang.SystemOut;
068import lucee.commons.lang.mimetype.MimeType;
069import lucee.commons.lang.types.RefBoolean;
070import lucee.commons.lang.types.RefBooleanImpl;
071import lucee.commons.lock.KeyLock;
072import lucee.commons.lock.Lock;
073import lucee.commons.net.HTTPUtil;
074import lucee.intergral.fusiondebug.server.FDSignal;
075import lucee.runtime.cache.tag.CacheHandler;
076import lucee.runtime.cache.tag.CacheHandlerFactory;
077import lucee.runtime.cache.tag.CacheItem;
078import lucee.runtime.cache.tag.include.IncludeCacheItem;
079import lucee.runtime.component.ComponentLoader;
080import lucee.runtime.config.Config;
081import lucee.runtime.config.ConfigImpl;
082import lucee.runtime.config.ConfigWeb;
083import lucee.runtime.config.ConfigWebImpl;
084import lucee.runtime.config.ConfigWebUtil;
085import lucee.runtime.config.Constants;
086import lucee.runtime.config.NullSupportHelper;
087import lucee.runtime.db.DataSource;
088import lucee.runtime.db.DataSourceManager;
089import lucee.runtime.db.DatasourceConnection;
090import lucee.runtime.db.DatasourceConnectionPool;
091import lucee.runtime.db.DatasourceManagerImpl;
092import lucee.runtime.debug.ActiveLock;
093import lucee.runtime.debug.ActiveQuery;
094import lucee.runtime.debug.DebugCFMLWriter;
095import lucee.runtime.debug.DebugEntryTemplate;
096import lucee.runtime.debug.Debugger;
097import lucee.runtime.debug.DebuggerImpl;
098import lucee.runtime.debug.DebuggerPro;
099import lucee.runtime.dump.DumpUtil;
100import lucee.runtime.dump.DumpWriter;
101import lucee.runtime.engine.ExecutionLog;
102import lucee.runtime.err.ErrorPage;
103import lucee.runtime.err.ErrorPageImpl;
104import lucee.runtime.err.ErrorPagePool;
105import lucee.runtime.exp.Abort;
106import lucee.runtime.exp.ApplicationException;
107import lucee.runtime.exp.CasterException;
108import lucee.runtime.exp.DatabaseException;
109import lucee.runtime.exp.ExceptionHandler;
110import lucee.runtime.exp.ExpressionException;
111import lucee.runtime.exp.MissingIncludeException;
112import lucee.runtime.exp.PageException;
113import lucee.runtime.exp.PageExceptionBox;
114import lucee.runtime.exp.PageExceptionImpl;
115import lucee.runtime.exp.PageServletException;
116import lucee.runtime.functions.dynamicEvaluation.Serialize;
117import lucee.runtime.interpreter.CFMLExpressionInterpreter;
118import lucee.runtime.interpreter.VariableInterpreter;
119import lucee.runtime.listener.AppListenerUtil;
120import lucee.runtime.listener.ApplicationContext;
121import lucee.runtime.listener.ApplicationContextPro;
122import lucee.runtime.listener.ApplicationListener;
123import lucee.runtime.listener.ClassicApplicationContext;
124import lucee.runtime.listener.JavaSettingsImpl;
125import lucee.runtime.listener.ModernAppListenerException;
126import lucee.runtime.monitor.RequestMonitor;
127import lucee.runtime.net.ftp.FTPPool;
128import lucee.runtime.net.ftp.FTPPoolImpl;
129import lucee.runtime.net.http.HTTPServletRequestWrap;
130import lucee.runtime.net.http.ReqRspUtil;
131import lucee.runtime.op.Caster;
132import lucee.runtime.op.Decision;
133import lucee.runtime.op.Operator;
134import lucee.runtime.orm.ORMConfiguration;
135import lucee.runtime.orm.ORMEngine;
136import lucee.runtime.orm.ORMSession;
137import lucee.runtime.query.QueryCache;
138import lucee.runtime.rest.RestRequestListener;
139import lucee.runtime.rest.RestUtil;
140import lucee.runtime.security.Credential;
141import lucee.runtime.security.CredentialImpl;
142import lucee.runtime.security.ScriptProtect;
143import lucee.runtime.tag.Login;
144import lucee.runtime.tag.TagHandlerPool;
145import lucee.runtime.tag.TagUtil;
146import lucee.runtime.type.Array;
147import lucee.runtime.type.Collection;
148import lucee.runtime.type.Collection.Key;
149import lucee.runtime.type.Iterator;
150import lucee.runtime.type.KeyImpl;
151import lucee.runtime.type.Query;
152import lucee.runtime.type.SVArray;
153import lucee.runtime.type.Sizeable;
154import lucee.runtime.type.Struct;
155import lucee.runtime.type.StructImpl;
156import lucee.runtime.type.UDF;
157import lucee.runtime.type.UDFPlus;
158import lucee.runtime.type.it.ItAsEnum;
159import lucee.runtime.type.ref.Reference;
160import lucee.runtime.type.ref.VariableReference;
161import lucee.runtime.type.scope.Application;
162import lucee.runtime.type.scope.Argument;
163import lucee.runtime.type.scope.ArgumentImpl;
164import lucee.runtime.type.scope.CGI;
165import lucee.runtime.type.scope.CGIImpl;
166import lucee.runtime.type.scope.CGIImplReadOnly;
167import lucee.runtime.type.scope.Client;
168import lucee.runtime.type.scope.ClosureScope;
169import lucee.runtime.type.scope.Cluster;
170import lucee.runtime.type.scope.Cookie;
171import lucee.runtime.type.scope.CookieImpl;
172import lucee.runtime.type.scope.Form;
173import lucee.runtime.type.scope.FormImpl;
174import lucee.runtime.type.scope.Local;
175import lucee.runtime.type.scope.LocalNotSupportedScope;
176import lucee.runtime.type.scope.Request;
177import lucee.runtime.type.scope.RequestImpl;
178import lucee.runtime.type.scope.Scope;
179import lucee.runtime.type.scope.ScopeContext;
180import lucee.runtime.type.scope.ScopeFactory;
181import lucee.runtime.type.scope.ScopeSupport;
182import lucee.runtime.type.scope.Server;
183import lucee.runtime.type.scope.Session;
184import lucee.runtime.type.scope.Threads;
185import lucee.runtime.type.scope.URL;
186import lucee.runtime.type.scope.URLForm;
187import lucee.runtime.type.scope.URLImpl;
188import lucee.runtime.type.scope.Undefined;
189import lucee.runtime.type.scope.UndefinedImpl;
190import lucee.runtime.type.scope.UrlFormImpl;
191import lucee.runtime.type.scope.Variables;
192import lucee.runtime.type.scope.VariablesImpl;
193import lucee.runtime.type.util.ArrayUtil;
194import lucee.runtime.type.util.CollectionUtil;
195import lucee.runtime.type.util.KeyConstants;
196import lucee.runtime.util.PageContextUtil;
197import lucee.runtime.util.VariableUtil;
198import lucee.runtime.util.VariableUtilImpl;
199import lucee.runtime.writer.BodyContentUtil;
200import lucee.runtime.writer.CFMLWriter;
201import lucee.runtime.writer.DevNullBodyContent;
202
203import org.apache.oro.text.regex.MalformedPatternException;
204import org.apache.oro.text.regex.Pattern;
205import org.apache.oro.text.regex.PatternMatcherInput;
206import org.apache.oro.text.regex.Perl5Compiler;
207import org.apache.oro.text.regex.Perl5Matcher;
208
209/**
210 * page context for every page object. 
211 * the PageContext is a jsp page context expanded by CFML functionality.
212 * for example you have the method getSession to get jsp combatible session object (HTTPSession)
213 *  and with sessionScope() you get CFML combatible session object (Struct,Scope).
214 */
215public final class PageContextImpl extends PageContext implements Sizeable {
216        
217        private static final RefBoolean DUMMY_BOOL = new RefBooleanImpl(false);
218        
219        private static int counter=0;
220        
221        /** 
222         * Field <code>pathList</code>
223         */
224    private LinkedList<UDF> udfs=new LinkedList<UDF>();
225    private LinkedList<PageSource> pathList=new LinkedList<PageSource>();
226    private LinkedList<PageSource> includePathList=new LinkedList<PageSource>();
227    private Set<PageSource> includeOnce=new HashSet<PageSource>();
228        
229        /**
230         * Field <code>executionTime</code>
231         */
232        protected long executionTime=0;
233        
234        private HTTPServletRequestWrap req;
235        private HttpServletResponse rsp;
236        private HttpServlet servlet;
237        
238        private JspWriter writer;
239    private JspWriter forceWriter;
240    private BodyContentStack bodyContentStack;
241    private DevNullBodyContent devNull;
242    
243        private ConfigWebImpl config;
244        //private DataSourceManager manager;
245        //private CFMLCompilerImpl compiler;
246        
247        // Scopes
248        private ScopeContext scopeContext;
249    private Variables variablesRoot=new VariablesImpl();//ScopeSupport(false,"variables",Scope.SCOPE_VARIABLES);
250    private Variables variables=variablesRoot;//new ScopeSupport("variables",Scope.SCOPE_VARIABLES);
251    private Undefined undefined;
252        
253    private URLImpl _url=new URLImpl();
254        private FormImpl _form=new FormImpl();
255        
256        private URLForm urlForm=new UrlFormImpl(_form,_url);
257        private URL url;
258        private Form form;
259        
260        
261        private RequestImpl request=new RequestImpl();
262        private CGIImplReadOnly cgiR=new CGIImplReadOnly();
263        private CGIImpl cgiRW=new CGIImpl();    
264        private Argument argument=new ArgumentImpl();
265    private static LocalNotSupportedScope localUnsupportedScope=LocalNotSupportedScope.getInstance();
266        private Local local=localUnsupportedScope;
267        private Session session;
268        private Server server;
269        private Cluster cluster;
270        private CookieImpl cookie=new CookieImpl();
271        private Client client;
272        private Application application;
273
274    private DebuggerPro debugger=new DebuggerImpl();
275        private long requestTimeout=-1;
276        private short enablecfoutputonly=0;
277        private int outputState;
278        private String cfid;
279        private String cftoken;
280
281        private int id;
282        private int requestId;
283        
284        
285        private boolean psq;
286        private Locale locale;
287        private TimeZone timeZone;
288        
289    // Pools
290    private ErrorPagePool errorPagePool=new ErrorPagePool();
291        private TagHandlerPool tagHandlerPool;
292        private FTPPoolImpl ftpPool=new FTPPoolImpl();
293        
294        private Component activeComponent;
295        private UDF activeUDF;
296        private Collection.Key activeUDFCalledName;
297    //private ComponentScope componentScope=new ComponentScope(this);
298        
299        private Credential remoteUser;
300    
301    protected VariableUtilImpl variableUtil=new VariableUtilImpl();
302
303    private PageException exception;
304    private PageSource base;
305
306    ApplicationContextPro applicationContext;
307    ApplicationContextPro defaultApplicationContext;
308
309    private ScopeFactory scopeFactory=new ScopeFactory();
310
311    private Tag parentTag=null;
312    private Tag currentTag=null;
313    private Thread thread;
314    private long startTime;
315        private boolean isCFCRequest;
316        
317        private DatasourceManagerImpl manager;
318        private Struct threads;
319        private boolean hasFamily=false;
320        //private CFMLFactoryImpl factory;
321        private PageContextImpl parent;
322        private Map<String,DatasourceConnection> transConns=new ConcurrentHashMap<String,DatasourceConnection>();
323        private List<Statement> lazyStats;
324        private boolean fdEnabled;
325        private ExecutionLog execLog;
326        private boolean useSpecialMappings;
327        
328
329        private ORMSession ormSession;
330        private boolean isChild;
331        private boolean gatewayContext;
332        private String serverPassword;
333
334        private PageException pe;
335
336        private Throwable requestTimeoutException;
337
338        private int appListenerType=AppListenerUtil.TYPE_ALL;
339
340        private boolean literalTimestampWithTSOffset;
341
342        public long sizeOf() {
343                
344                return 
345                SizeOf.size(pathList)+
346                SizeOf.size(includePathList)+
347                SizeOf.size(executionTime)+
348                SizeOf.size(writer)+
349                SizeOf.size(forceWriter)+
350                SizeOf.size(bodyContentStack)+
351                SizeOf.size(variables)+
352                SizeOf.size(url)+
353                SizeOf.size(form)+
354                SizeOf.size(_url)+
355                SizeOf.size(_form)+
356                SizeOf.size(request)+
357
358                SizeOf.size(argument)+
359                SizeOf.size(local)+
360                SizeOf.size(cookie)+
361                SizeOf.size(debugger)+
362                SizeOf.size(requestTimeout)+
363                SizeOf.size(enablecfoutputonly)+
364                SizeOf.size(outputState)+
365                SizeOf.size(cfid)+
366                SizeOf.size(cftoken)+
367                SizeOf.size(id)+
368                SizeOf.size(psq)+
369                SizeOf.size(locale)+
370                SizeOf.size(errorPagePool)+
371                SizeOf.size(tagHandlerPool)+
372                SizeOf.size(ftpPool)+
373                SizeOf.size(activeComponent)+
374                SizeOf.size(activeUDF)+
375                SizeOf.size(remoteUser)+
376                SizeOf.size(exception)+
377                SizeOf.size(base)+
378                SizeOf.size(applicationContext)+
379                SizeOf.size(defaultApplicationContext)+
380                SizeOf.size(parentTag)+
381                SizeOf.size(currentTag)+
382                SizeOf.size(startTime)+
383                SizeOf.size(isCFCRequest)+
384                SizeOf.size(transConns)+
385                SizeOf.size(lazyStats)+
386                SizeOf.size(serverPassword)+
387                SizeOf.size(ormSession);
388        }
389        
390        
391
392        /** 
393         * default Constructor
394         * @param scopeContext
395         * @param config Configuration of the CFML Container
396         * @param queryCache Query Cache Object
397         * @param id identity of the pageContext
398         * @param servlet
399         */
400        public PageContextImpl(ScopeContext scopeContext, ConfigWebImpl config, int id,HttpServlet servlet) {
401                // must be first because is used after
402                tagHandlerPool=config.getTagHandlerPool();
403        this.servlet=servlet;
404                this.id=id;
405                //this.factory=factory;
406                
407        bodyContentStack=new BodyContentStack();
408        devNull=bodyContentStack.getDevNullBodyContent();
409        
410        this.config=config;
411        manager=new DatasourceManagerImpl(config);
412        
413            this.scopeContext=scopeContext;
414        undefined=
415                new UndefinedImpl(this,getScopeCascadingType());
416        server=ScopeContext.getServerScope(this);
417                
418                defaultApplicationContext=new ClassicApplicationContext(config,"",true,null);
419                
420        }
421
422        @Override
423        public void initialize(
424                        Servlet servlet, 
425                        ServletRequest req, 
426                        ServletResponse rsp, 
427                        String errorPageURL, 
428                        boolean needsSession, 
429                        int bufferSize, 
430                        boolean autoFlush) throws IOException, IllegalStateException, IllegalArgumentException {
431                initialize(
432                           (HttpServlet)servlet,
433                           (HttpServletRequest)req,
434                           (HttpServletResponse)rsp,
435                           errorPageURL,
436                           needsSession,
437                           bufferSize,
438                           autoFlush,false);
439        }
440        
441
442        public boolean isInitialized() {
443                return rsp!=null;
444        }
445        
446
447        /**
448         * return if the PageContext is from a stopped thread, if so it should no longer be used!
449         * @return
450         */
451        public Throwable getStopPosition() {
452                return requestTimeoutException;
453        }
454        public void stop(Throwable requestTimeoutException) {
455                this.requestTimeoutException=requestTimeoutException;
456        }
457        
458        
459        /**
460         * initialize a existing page context
461         * @param servlet
462         * @param req
463         * @param rsp
464         * @param errorPageURL
465         * @param needsSession
466         * @param bufferSize
467         * @param autoFlush
468         */
469        public PageContextImpl initialize(
470                         HttpServlet servlet, 
471                         HttpServletRequest req, 
472                         HttpServletResponse rsp, 
473                         String errorPageURL, 
474                         boolean needsSession, 
475                         int bufferSize, 
476                         boolean autoFlush,
477                         boolean isChild) {
478                requestId=counter++;
479                rsp.setContentType("text/html; charset=UTF-8");
480                this.isChild=isChild;
481                appListenerType=AppListenerUtil.TYPE_ALL;
482        //rsp.setHeader("Connection", "close");
483        applicationContext=defaultApplicationContext;
484        
485        startTime=System.currentTimeMillis();
486        thread=Thread.currentThread();
487        
488        isCFCRequest = StringUtil.endsWithIgnoreCase(req.getServletPath(),"."+config.getCFCExtension());
489        
490        this.req=new HTTPServletRequestWrap(req);
491        this.rsp=rsp;
492        this.servlet=servlet;
493
494         // Writers
495        if(config.debugLogOutput()) {
496                CFMLWriter w = config.getCFMLWriter(this,req,rsp);
497                w.setAllowCompression(false);
498                DebugCFMLWriter dcw = new DebugCFMLWriter(w);
499                bodyContentStack.init(dcw);
500                debugger.setOutputLog(dcw);
501        }
502        else {
503                bodyContentStack.init(config.getCFMLWriter(this,req,rsp));
504        }
505        
506                
507        writer=bodyContentStack.getWriter();
508        forceWriter=writer;
509         
510                 // Scopes
511         server=ScopeContext.getServerScope(this);
512         if(hasFamily) {
513                 variablesRoot=new VariablesImpl();
514                 variables=variablesRoot;
515                 request=new RequestImpl();
516                 _url=new URLImpl();
517                 _form=new FormImpl();
518                 urlForm=new UrlFormImpl(_form,_url);
519                 undefined=
520                new UndefinedImpl(this,getScopeCascadingType());
521                 
522                 hasFamily=false;
523         }
524         else if(variables==null) {
525                 variablesRoot=new VariablesImpl();
526                 variables=variablesRoot;
527         }
528         request.initialize(this);
529         
530                 if(config.mergeFormAndURL()) {
531                         url=urlForm;
532                         form=urlForm;
533                 }
534                 else {
535                         url=_url;
536                         form=_form;
537                 }
538         //url.initialize(this);
539                 //form.initialize(this);
540                 //undefined.initialize(this);
541                 
542         
543        psq=config.getPSQL();
544                
545                fdEnabled=!config.allowRequestTimeout();
546                
547                if(config.getExecutionLogEnabled())
548                        this.execLog=config.getExecutionLogFactory().getInstance(this);
549                if(debugger!=null)
550                        debugger.init(config);
551                
552                undefined.initialize(this);
553                return this;
554         }
555        
556        @Override
557        public void release() {
558                ConfigWebUtil.getCacheHandlerFactories(getConfig()).release(this);
559                
560        if(config.getExecutionLogEnabled()){
561                execLog.release();
562                        execLog=null;
563        }
564                
565                if(config.debug()) {
566                if(!gatewayContext && !isChild)
567                            config.getDebuggerPool().store(this, debugger);
568                debugger.reset();
569        }
570                else ((DebuggerImpl)debugger).resetTraces(); // traces can alo be used when debugging is off
571                
572                this.serverPassword=null;
573
574//              boolean isChild=parent!=null;       // isChild is defined in the class outside this method
575                parent=null;
576                // Attention have to be before close
577                if(client!=null){
578                client.touchAfterRequest(this);
579                client=null;
580        }
581                if(session!=null){
582                session.touchAfterRequest(this);
583                session=null;
584        }
585                
586                // ORM
587        if(ormSession!=null){
588                // flush orm session
589                try {
590                                ORMEngine engine=ormSession.getEngine();
591                        ORMConfiguration config=engine.getConfiguration(this);
592                        if(config==null || (config.flushAtRequestEnd() && config.autoManageSession())){
593                                        ormSession.flushAll(this);
594                                }
595                                ormSession.closeAll(this);
596                        } 
597                catch (Throwable t) {
598                        ExceptionUtil.rethrowIfNecessary(t);
599                        //print.printST(t);
600                }
601                ormSession=null;
602        }
603        
604
605        // Scopes
606        if(hasFamily) {
607                if(!isChild){
608                        req.disconnect(this);
609                }
610                
611                close();
612            thread=null;
613            base=null;
614            
615                
616                request=null;
617                _url=null;
618                _form=null;
619            urlForm=null;
620            undefined=null;
621            variables=null;
622            variablesRoot=null;
623            if(threads!=null && threads.size()>0) threads.clear();
624            
625        }
626        else {
627                close();
628            thread=null;
629            base=null;
630            
631                
632            if(variables.isBind()) {
633                variables=null;
634                variablesRoot=null;
635            }
636            else {
637                variables=variablesRoot;
638                variables.release(this);
639            }
640            undefined.release(this);
641            urlForm.release(this);
642                request.release();
643        }
644        cgiR.release(this);
645        cgiRW.release(this);
646        
647        argument.release(this);
648        local=localUnsupportedScope;
649        
650        cookie.release();
651                //if(cluster!=null)cluster.release();
652        
653        //client=null;
654        //session=null;
655        
656                
657        
658        
659                application=null;// not needed at the moment -> application.releaseAfterRequest();
660                applicationContext=null;
661                
662                // Properties
663        requestTimeout=-1;
664        outputState=0;
665        cfid=null;
666        cftoken=null;
667        locale=null;
668        timeZone=null;
669        url=null;
670        form=null;
671        
672        
673        // Pools
674        errorPagePool.clear();
675
676        // transaction connection
677        if(!transConns.isEmpty()){
678                java.util.Iterator<DatasourceConnection> it = transConns.values().iterator();
679                DatasourceConnectionPool pool = config.getDatasourceConnectionPool();
680                while(it.hasNext())     {
681                        pool.releaseDatasourceConnection(config,(it.next()),true);
682                }
683                transConns.clear();
684        }
685        
686
687        // lazy statements
688        if(lazyStats!=null && !lazyStats.isEmpty()){
689                java.util.Iterator<Statement> it = lazyStats.iterator();
690                while(it.hasNext())     {
691                        DBUtil.closeEL(it.next());
692                }
693                lazyStats.clear();
694                lazyStats=null;
695        }
696        
697        
698        
699        pathList.clear();
700        includePathList.clear();
701                executionTime=0;
702                
703                bodyContentStack.release();
704                
705
706        
707                //activeComponent=null;
708                remoteUser=null;
709                exception=null;
710                ftpPool.clear();
711        parentTag=null;
712        currentTag=null;
713        
714        // Req/Rsp
715        //if(req!=null)
716                req.clear();
717        req=null;
718        rsp=null;
719        servlet=null;
720
721        // Writer
722        writer=null;
723        forceWriter=null;
724        if(pagesUsed.size()>0)pagesUsed.clear();
725        
726        activeComponent=null;
727        activeUDF=null;
728        
729
730        gatewayContext=false;
731        
732        manager.release();
733        includeOnce.clear();
734        pe=null;
735        
736        literalTimestampWithTSOffset=false;
737
738        }
739
740        @Override
741    public void write(String str) throws IOException {
742        writer.write(str);
743        }
744
745    @Override
746    public void forceWrite(String str) throws IOException {
747        forceWriter.write(str);
748    }
749        
750    @Override
751    public void writePSQ(Object o) throws IOException, PageException {
752        if(o instanceof Date || Decision.isDate(o, false)) {
753                        writer.write(Caster.toString(o));
754                }
755                else {
756            writer.write(psq?Caster.toString(o):StringUtil.replace(Caster.toString(o),"'","''",false));
757                }
758        } 
759        
760    @Override
761    public void flush() {
762                try {
763                        getOut().flush();
764                } catch (IOException e) {}
765        }
766        
767    @Override
768    public void close() {
769        IOUtil.closeEL(getOut());
770        }
771        
772    public PageSource getRelativePageSource(String relPath) {
773        SystemOut.print(config.getOutWriter(),"method getRelativePageSource is deprecated");
774        if(StringUtil.startsWith(relPath,'/')) return PageSourceImpl.best(getPageSources(relPath));
775        if(pathList.size()==0) return null;
776                return pathList.getLast().getRealPage(relPath);
777        }
778    
779   public PageSource getRelativePageSourceExisting(String relPath) {
780        if(StringUtil.startsWith(relPath,'/')) return getPageSourceExisting(relPath);
781        if(pathList.size()==0) return null;
782                PageSource ps = pathList.getLast().getRealPage(relPath);
783                if(PageSourceImpl.pageExist(ps)) return ps;
784                return null;
785        }
786    
787     /**
788     * 
789     * @param relPath
790     * @param previous relative not to the caller, relative to the callers caller
791     * @return
792     */
793    public PageSource getRelativePageSourceExisting(String relPath, boolean previous ) {
794        if(StringUtil.startsWith(relPath,'/')) return getPageSourceExisting(relPath);
795        if(pathList.size()==0) return null;
796        
797        PageSource ps=null,tmp=null;
798        if(previous) {
799                boolean valid=false;
800                ps=pathList.getLast();
801                for(int i=pathList.size()-2;i>=0;i--){
802                        tmp=pathList.get(i);
803                        if(tmp!=ps) {
804                                ps=tmp;
805                                valid=true;
806                                break;
807                        }
808                }
809                if(!valid) return null;
810        }
811        else ps=pathList.getLast();
812        
813        ps = ps.getRealPage(relPath);
814                if(PageSourceImpl.pageExist(ps)) return ps;
815                return null;
816        }
817    
818    public PageSource[] getRelativePageSources(String relPath) {
819        if(StringUtil.startsWith(relPath,'/')) return getPageSources(relPath);
820        if(pathList.size()==0) return null;
821                return new PageSource[]{ pathList.getLast().getRealPage(relPath)};
822        }
823    
824    public PageSource getPageSource(String relPath) {
825        SystemOut.print(config.getOutWriter(),"method getPageSource is deprecated");
826        return PageSourceImpl.best(config.getPageSources(this,applicationContext.getMappings(),relPath,false,useSpecialMappings,true));
827        }
828    
829    public PageSource[] getPageSources(String relPath) {
830        return config.getPageSources(this,applicationContext.getMappings(),relPath,false,useSpecialMappings,true);
831        }
832    
833    public PageSource getPageSourceExisting(String relPath) {
834        return config.getPageSourceExisting(this,applicationContext.getMappings(),relPath,false,useSpecialMappings,true,false);
835        }
836
837    public boolean useSpecialMappings(boolean useTagMappings) {
838                boolean b=this.useSpecialMappings;
839                this.useSpecialMappings=useTagMappings;
840                return b;
841        }
842    public boolean useSpecialMappings() {
843                return useSpecialMappings;
844        }
845    
846
847    public Resource getPhysical(String relPath, boolean alsoDefaultMapping){
848        return config.getPhysical(applicationContext.getMappings(),relPath, alsoDefaultMapping);
849    }
850    
851
852        public PageSource toPageSource(Resource res, PageSource defaultValue){
853                return config.toPageSource(applicationContext.getMappings(),res, defaultValue);
854        }
855
856        @Override
857        public void doInclude(String relPath) throws PageException {
858                doInclude(getRelativePageSources(relPath),false);
859        }
860        
861        @Override
862        public void doInclude(String relPath, boolean runOnce) throws PageException {
863                doInclude(getRelativePageSources(relPath),runOnce);
864        }
865        
866        public void doInclude(String relPath, boolean runOnce, Object cachedWithin) throws PageException {
867                if(cachedWithin==null) {
868                        doInclude(relPath, runOnce);
869                }
870                
871                // ignore call when runonce an it is not first call 
872                PageSource[] sources = getRelativePageSources(relPath);
873                if(runOnce) {
874                        Page currentPage = PageSourceImpl.loadPage(this, sources);
875                        if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
876                }
877                
878                // get cached data
879                String id=CacheHandlerFactory.createId(sources);
880                CacheHandler ch = ConfigWebUtil.getCacheHandlerFactories(getConfig()).include.getInstance(getConfig(), cachedWithin);
881                CacheItem ci=ch.get(this, id);
882                
883                if(ci instanceof IncludeCacheItem) {
884                        try {
885                                write(((IncludeCacheItem)ci).getOutput());
886                                return;
887                        } catch (IOException e) {
888                                throw Caster.toPageException(e);
889                        }
890                }
891                long start = System.nanoTime();
892        
893                BodyContent bc =  pushBody();
894            
895            try {
896                doInclude(sources, runOnce);
897                String out = bc.getString();
898                ch.set(this, id,cachedWithin,new IncludeCacheItem(
899                                out
900                                ,ArrayUtil.isEmpty(sources)?null:sources[0]
901                                ,System.nanoTime()-start));
902                        return;
903                }
904        finally {
905                BodyContentUtil.flushAndPop(this,bc);
906        }
907        }
908
909        @Override
910        public void doInclude(PageSource source) throws PageException {
911                doInclude(new PageSource[]{source},false);
912        }
913
914        @Override
915        public void doInclude(PageSource[] sources, boolean runOnce) throws PageException {
916        // debug
917                if(!gatewayContext && config.debug()) {
918                        final long currTime=executionTime;
919            long exeTime=0;
920            long time=System.nanoTime();
921            
922            Page currentPage = PageSourceImpl.loadPage(this, sources);
923                        if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
924            DebugEntryTemplate debugEntry=debugger.getEntry(this,currentPage.getPageSource());
925            try {
926                addPageSource(currentPage.getPageSource(),true);
927                debugEntry.updateFileLoadTime((System.nanoTime()-time));
928                exeTime=System.nanoTime();
929
930                currentPage.call(this);
931                        }
932                        catch(Throwable t){
933                                PageException pe = Caster.toPageException(t);
934                                if(Abort.isAbort(pe)) {
935                    if(Abort.isAbort(pe,Abort.SCOPE_REQUEST))throw pe;
936                }
937                else {
938                        if(fdEnabled){
939                                FDSignal.signal(pe, false);
940                        }
941                        pe.addContext(currentPage.getPageSource(),-187,-187, null);// TODO was soll das 187
942                        throw pe;
943                }
944                        }
945                        finally {
946                                includeOnce.add(currentPage.getPageSource());
947                                long diff= ((System.nanoTime()-exeTime)-(executionTime-currTime));
948                                executionTime+=(System.nanoTime()-time);
949                                debugEntry.updateExeTime(diff);
950                                removeLastPageSource(true);
951                        }       
952                }
953        // no debug
954                else {
955                        Page currentPage = PageSourceImpl.loadPage(this, sources);
956                        if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
957                try {
958                                addPageSource(currentPage.getPageSource(),true);
959                currentPage.call(this);
960                        }
961                        catch(Throwable t){
962                                PageException pe = Caster.toPageException(t);
963                                if(Abort.isAbort(pe)) {
964                                        if(Abort.isAbort(pe,Abort.SCOPE_REQUEST))throw pe;
965                }
966                else {
967                        pe.addContext(currentPage.getPageSource(),-187,-187, null);
968                        throw pe;
969                }
970                        }
971                        finally {
972                                includeOnce.add(currentPage.getPageSource());
973                                removeLastPageSource(true);
974                        }       
975                }
976        }
977
978        @Override
979    public Array getTemplatePath() throws PageException {
980        int len=includePathList.size();
981        SVArray sva = new SVArray();
982        PageSource ps;
983        for(int i=0;i<len;i++) {
984                ps=includePathList.get(i);
985                if(i==0) {
986                        if(!ps.equals(getBasePageSource()))
987                                sva.append(getBasePageSource().getResourceTranslated(this).getAbsolutePath());
988                }
989                sva.append(ps.getResourceTranslated(this).getAbsolutePath());
990        }
991        //sva.setPosition(sva.size());
992        return sva;
993    }
994  
995    public List<PageSource> getPageSourceList() {
996        return (List<PageSource>) pathList.clone();
997    }
998    
999    
1000    
1001    public PageSource getPageSource(int index) {
1002        return includePathList.get(index-1);
1003    }
1004    public synchronized void copyStateTo(PageContextImpl other) {
1005        
1006                // cfid (we do this that way, otherwise we only have the same cfid if the current pc has defined cfid in cookie or url)
1007                getCFID(); 
1008                other.cfid=cfid;
1009                other.cftoken=cftoken;
1010
1011        // private Debugger debugger=new DebuggerImpl();
1012        other.requestTimeout=requestTimeout;
1013        other.locale=locale;
1014        other.timeZone=timeZone;
1015        other.fdEnabled=fdEnabled;
1016        other.useSpecialMappings=useSpecialMappings;
1017        other.serverPassword=serverPassword;
1018        
1019        
1020        hasFamily=true;
1021        other.hasFamily=true;
1022        other.parent=this;
1023                other.applicationContext=applicationContext;
1024                other.thread=Thread.currentThread();
1025                other.startTime=System.currentTimeMillis();
1026                other.isCFCRequest = isCFCRequest;
1027        
1028        
1029        
1030        // path
1031        other.base=base;
1032        java.util.Iterator<PageSource> it = includePathList.iterator();
1033        while(it.hasNext()) {
1034                other.includePathList.add(it.next());
1035        }
1036        it = pathList.iterator();
1037        while(it.hasNext()) {
1038                other.pathList.add(it.next());
1039        }
1040        
1041        
1042        // scopes
1043        other.req=req;
1044        other.request=request;
1045        other.form=form;
1046        other.url=url;
1047        other.urlForm=urlForm;
1048        other._url=_url;
1049        other._form=_form;
1050        other.variables=variables;
1051        other.undefined=new UndefinedImpl(other,(short)other.undefined.getType());
1052        
1053        // writers
1054        other.bodyContentStack.init(config.getCFMLWriter(this,other.req,other.rsp));
1055        //other.bodyContentStack.init(other.req,other.rsp,other.config.isSuppressWhitespace(),other.config.closeConnection(), other.config.isShowVersion(),config.contentLength(),config.allowCompression());
1056        other.writer=other.bodyContentStack.getWriter();
1057        other.forceWriter=other.writer;
1058        
1059        other.psq=psq;
1060        other.gatewayContext=gatewayContext;
1061        
1062        // thread
1063        if(threads!=null){
1064                synchronized (threads) {
1065                                
1066                        java.util.Iterator<Entry<Key, Object>> it2 = threads.entryIterator();
1067                        Entry<Key, Object> entry;
1068                        while(it2.hasNext()) {
1069                                entry = it2.next();
1070                                other.setThreadScope(entry.getKey(), (Threads)entry.getValue());
1071                        }
1072                        }
1073        }
1074        
1075        
1076        // initialize stuff
1077        other.undefined.initialize(other);
1078        
1079        
1080    }
1081    
1082    public int getCurrentLevel() {
1083        return includePathList.size()+1;
1084    }
1085    
1086    /**
1087     * @return the current template PageSource
1088     */
1089    public PageSource getCurrentPageSource() {
1090        if(pathList.isEmpty()) return null;
1091        return pathList.getLast();
1092    }
1093    public PageSource getCurrentPageSource(PageSource defaultvalue) {
1094        if(pathList.isEmpty()) return defaultvalue;
1095        return pathList.getLast();
1096    }
1097    
1098    /**
1099     * @return the current template PageSource
1100     */
1101    public PageSource getCurrentTemplatePageSource() {
1102        return includePathList.getLast();
1103    }
1104        
1105    /**
1106     * @return base template file
1107     */
1108    public PageSource getBasePageSource() {
1109                return base;
1110        }
1111        
1112    @Override
1113    public Resource getRootTemplateDirectory() {
1114                return config.getResource(ReqRspUtil.getRootPath(servlet.getServletContext()));
1115        }
1116
1117    @Override
1118    public Scope scope(int type) throws PageException {
1119        switch(type) {
1120            case Scope.SCOPE_UNDEFINED:     return undefinedScope();
1121            case Scope.SCOPE_URL:           return urlScope();
1122            case Scope.SCOPE_FORM:          return formScope();
1123            case Scope.SCOPE_VARIABLES:     return variablesScope();
1124            case Scope.SCOPE_REQUEST:       return requestScope();
1125            case Scope.SCOPE_CGI:           return cgiScope();
1126            case Scope.SCOPE_APPLICATION:   return applicationScope();
1127            case Scope.SCOPE_ARGUMENTS:     return argumentsScope();
1128            case Scope.SCOPE_SESSION:       return sessionScope();
1129            case Scope.SCOPE_SERVER:        return serverScope();
1130            case Scope.SCOPE_COOKIE:        return cookieScope();
1131            case Scope.SCOPE_CLIENT:        return clientScope();
1132            case Scope.SCOPE_LOCAL:         
1133            case ScopeSupport.SCOPE_VAR:                return localScope();
1134            case Scope.SCOPE_CLUSTER:return clusterScope();
1135        }
1136        return variables;
1137    }
1138    
1139    public Scope scope(String strScope,Scope defaultValue) throws PageException {
1140        if(strScope==null)return defaultValue;
1141        strScope=strScope.toLowerCase().trim(); 
1142        if("variables".equals(strScope))        return variablesScope(); 
1143        if("url".equals(strScope))                      return urlScope();
1144        if("form".equals(strScope))                     return formScope();
1145        if("request".equals(strScope))          return requestScope();
1146        if("cgi".equals(strScope))                      return cgiScope();
1147        if("application".equals(strScope))      return applicationScope();
1148        if("arguments".equals(strScope))        return argumentsScope();
1149        if("session".equals(strScope))          return sessionScope();
1150        if("server".equals(strScope))           return serverScope();
1151        if("cookie".equals(strScope))           return cookieScope();
1152        if("client".equals(strScope))           return clientScope();
1153        if("local".equals(strScope))            return localScope();
1154        if("cluster".equals(strScope))          return clusterScope();
1155        
1156            return defaultValue;
1157    }
1158    
1159    @Override
1160    public Undefined undefinedScope() {
1161        if(!undefined.isInitalized()) undefined.initialize(this);
1162        return undefined;
1163    }
1164    
1165    /**
1166     * @return undefined scope, undefined scope is a placeholder for the scopecascading
1167     */
1168    public Undefined us() {
1169        if(!undefined.isInitalized()) undefined.initialize(this);
1170        return undefined;
1171    }
1172    
1173    @Override
1174    public Variables variablesScope() { return variables; }
1175        
1176    @Override
1177    public URL urlScope() { 
1178        if(!url.isInitalized())url.initialize(this);
1179                return url;
1180    }
1181        
1182    @Override
1183    public Form formScope() {
1184        if(!form.isInitalized())form.initialize(this);
1185                return form;
1186    }
1187        
1188    @Override
1189    public URLForm urlFormScope() {
1190        if(!urlForm.isInitalized())urlForm.initialize(this);
1191                return urlForm;
1192    }
1193
1194    @Override
1195    public Request requestScope() { return request; }
1196        
1197    @Override
1198    public CGI cgiScope() {
1199        CGI cgi=applicationContext.getCGIScopeReadonly()?cgiR:cgiRW;
1200        if(!cgi.isInitalized())cgi.initialize(this);
1201                return cgi;
1202        }
1203        
1204    @Override
1205    public Application applicationScope() throws PageException {
1206                if(application==null) {
1207                        if(!applicationContext.hasName())
1208                                throw new ExpressionException("there is no application context defined for this application","you can define a application context with the tag "+lucee.runtime.config.Constants.CFAPP_NAME+"/"+lucee.runtime.config.Constants.APP_CFC);
1209                        application=scopeContext.getApplicationScope(this,DUMMY_BOOL);
1210                }
1211                return application; 
1212        }
1213
1214    @Override
1215    public Argument argumentsScope() { return argument; }
1216
1217    
1218    @Override
1219    public Argument argumentsScope(boolean bind) { 
1220            //Argument a=argumentsScope(); 
1221            if(bind)argument.setBind(true); 
1222            return argument; 
1223    } 
1224    
1225    @Override
1226    public Local localScope() { 
1227        //if(local==localUnsupportedScope) 
1228        //      throw new PageRuntimeException(new ExpressionException("Unsupported Context for Local Scope"));
1229        return local;
1230    }
1231    
1232    @Override
1233    public Local localScope(boolean bind) { 
1234        if(bind)local.setBind(true); 
1235        //if(local==localUnsupportedScope) 
1236        //      throw new PageRuntimeException(new ExpressionException("Unsupported Context for Local Scope"));
1237        return local; 
1238    }
1239
1240
1241    public Object localGet() throws PageException { 
1242        return localGet(false);
1243    }
1244    
1245    public Object localGet(boolean bind, Object defaultValue) { 
1246        if(undefined.getCheckArguments()){
1247                return localScope(bind);
1248        }
1249        return undefinedScope().get(KeyConstants._local,defaultValue);
1250    }
1251    
1252    public Object localGet(boolean bind) throws PageException { 
1253        // inside a local supported block
1254        if(undefined.getCheckArguments()){
1255                return localScope(bind);
1256        }
1257        return undefinedScope().get(KeyConstants._local);
1258    }
1259
1260    public Object localTouch() throws PageException { 
1261        return localTouch(false);
1262    }
1263    
1264    public Object localTouch(boolean bind) throws PageException { 
1265        // inside a local supported block
1266        if(undefined.getCheckArguments()){
1267                return localScope(bind);
1268        }
1269        return touch(undefinedScope(), KeyConstants._local);
1270        //return undefinedScope().get(LOCAL);
1271    }
1272    
1273    public Object thisGet() throws PageException { 
1274        return thisTouch();
1275    }
1276
1277    public Object thisTouch() throws PageException {
1278        // inside a component
1279        if(undefined.variablesScope() instanceof ComponentScope){
1280                return ((ComponentScope)undefined.variablesScope()).getComponent();
1281        }
1282        return undefinedScope().get(KeyConstants._THIS);
1283    }
1284    
1285    public Object thisGet(Object defaultValue) { 
1286        return thisTouch(defaultValue);
1287    }
1288
1289    public Object thisTouch(Object defaultValue) {
1290        // inside a component
1291        if(undefined.variablesScope() instanceof ComponentScope){
1292                return ((ComponentScope)undefined.variablesScope()).getComponent();
1293        }
1294        return undefinedScope().get(KeyConstants._THIS,defaultValue);
1295    }
1296    
1297        
1298    /**
1299     * @param local sets the current local scope
1300     * @param argument sets the current argument scope
1301     */
1302    public void setFunctionScopes(Local local,Argument argument) {
1303        this.argument=argument;
1304                this.local=local;
1305                undefined.setFunctionScopes(local,argument);
1306        }
1307        
1308    @Override
1309    public Session sessionScope() throws PageException {
1310                return sessionScope(true);
1311        }
1312    public Session sessionScope(boolean checkExpires) throws PageException {
1313                if(session==null)       {
1314                        checkSessionContext();
1315                        session=scopeContext.getSessionScope(this,DUMMY_BOOL);
1316                }
1317                return session;
1318        }
1319
1320
1321        public void invalidateUserScopes(boolean migrateSessionData,boolean migrateClientData) throws PageException {
1322                checkSessionContext();
1323                scopeContext.invalidateUserScope(this, migrateSessionData, migrateClientData);
1324        }
1325    
1326    private void checkSessionContext() throws ExpressionException {
1327        if(!applicationContext.hasName())
1328                        throw new ExpressionException("there is no session context defined for this application","you can define a session context with the tag "+Constants.CFAPP_NAME+"/"+Constants.APP_CFC);
1329                if(!applicationContext.isSetSessionManagement())
1330                        throw new ExpressionException("session scope is not enabled","you can enable session scope with tag "+Constants.CFAPP_NAME+"/"+Constants.APP_CFC);
1331        }
1332
1333    @Override
1334    public Server serverScope() { 
1335                //if(!server.isInitalized()) server.initialize(this);
1336                return server;
1337        }
1338        
1339    public void reset() {
1340        server=ScopeContext.getServerScope(this);
1341        }
1342    
1343        @Override
1344    public Cluster clusterScope() throws PageException {
1345        return clusterScope(true);
1346        }
1347    
1348    public Cluster clusterScope(boolean create) throws PageException { 
1349        if(cluster==null && create) {
1350                cluster=ScopeContext.getClusterScope(config,create);
1351                //cluster.initialize(this);
1352        }
1353        //else if(!cluster.isInitalized()) cluster.initialize(this);
1354                return cluster;
1355        }
1356
1357    @Override
1358    public Cookie cookieScope() { 
1359        if(!cookie.isInitalized()) cookie.initialize(this);
1360        return cookie;
1361    }
1362        
1363    @Override
1364    public Client clientScope() throws PageException { 
1365                if(client==null) {
1366                        if(!applicationContext.hasName())
1367                                throw new ExpressionException("there is no client context defined for this application",
1368                                                "you can define a client context with the tag "+Constants.CFAPP_NAME+"/"+Constants.APP_CFC);
1369                        if(!applicationContext.isSetClientManagement())
1370                                throw new ExpressionException("client scope is not enabled",
1371                                                "you can enable client scope with tag "+Constants.CFAPP_NAME+"/"+Constants.APP_CFC);
1372                        
1373                        client= scopeContext.getClientScope(this);
1374                }
1375                return client;
1376        }
1377    
1378    public Client clientScopeEL() { 
1379                if(client==null) {
1380                        if(applicationContext==null || !applicationContext.hasName())                           return null;
1381                        if(!applicationContext.isSetClientManagement()) return null;
1382                        client= scopeContext.getClientScopeEL(this);
1383                }
1384                return client;
1385        }
1386        
1387    @Override
1388    public Object set(Object coll, String key, Object value) throws PageException {
1389            return variableUtil.set(this,coll,key,value);
1390        }
1391
1392        public Object set(Object coll, Collection.Key key, Object value) throws PageException {
1393                return variableUtil.set(this,coll,key,value);
1394        }
1395        
1396    @Override
1397    public Object touch(Object coll, String key) throws PageException {
1398            Object o=getCollection(coll,key,null);
1399            if(o!=null) return o;
1400            return set(coll,key,new StructImpl());
1401        } 
1402
1403        @Override
1404        public Object touch(Object coll, Collection.Key key) throws PageException {
1405                Object o=getCollection(coll,key,null);
1406            if(o!=null) return o;
1407            return set(coll,key,new StructImpl());
1408        }
1409    
1410    /*private Object _touch(Scope scope, String key) throws PageException {
1411            Object o=scope.get(key,null);
1412            if(o!=null) return o;
1413            return scope.set(key, new StructImpl());
1414        }*/     
1415    
1416
1417    
1418    
1419
1420    @Override
1421    public Object getCollection(Object coll, String key) throws PageException {
1422        return variableUtil.getCollection(this,coll,key);
1423        }
1424
1425        @Override
1426        public Object getCollection(Object coll, Collection.Key key) throws PageException {
1427                return variableUtil.getCollection(this,coll,key);
1428        }
1429        
1430    @Override
1431    public Object getCollection(Object coll, String key, Object defaultValue) {
1432                return variableUtil.getCollection(this,coll,key,defaultValue);
1433        }
1434
1435        @Override
1436        public Object getCollection(Object coll, Collection.Key key, Object defaultValue) {
1437                return variableUtil.getCollection(this,coll,key,defaultValue);
1438        }
1439        
1440    @Override
1441    public Object get(Object coll, String key) throws PageException {
1442                return variableUtil.get(this,coll,key);
1443        }
1444
1445        @Override
1446        public Object get(Object coll, Collection.Key key) throws PageException {
1447                return variableUtil.get(this,coll,key);
1448        }
1449        
1450    @Override
1451    public Reference getReference(Object coll, String key) throws PageException {
1452                return new VariableReference(coll,key);
1453        }
1454
1455        public Reference getReference(Object coll, Collection.Key key) throws PageException {
1456                return new VariableReference(coll,key);
1457        }
1458
1459    @Override
1460    public Object get(Object coll, String key, Object defaultValue) {
1461        return variableUtil.get(this,coll,key, defaultValue);
1462    }
1463
1464        @Override
1465        public Object get(Object coll, Collection.Key key, Object defaultValue) {
1466                return variableUtil.get(this,coll,key, defaultValue);
1467        }
1468        
1469    @Override
1470    public Object setVariable(String var, Object value) throws PageException {
1471            //return new CFMLExprInterpreter().interpretReference(this,new ParserString(var)).set(value);
1472            return VariableInterpreter.setVariable(this,var,value);
1473        }
1474    
1475    @Override
1476    public Object getVariable(String var) throws PageException {
1477                return VariableInterpreter.getVariable(this,var);
1478        }
1479    
1480
1481    public void param(String type, String name, Object defaultValue,String regex) throws PageException {
1482        param(type, name, defaultValue,Double.NaN,Double.NaN,regex,-1);
1483    }
1484        public void param(String type, String name, Object defaultValue,double min, double max) throws PageException {
1485        param(type, name, defaultValue,min,max,null,-1);
1486    }
1487
1488    public void param(String type, String name, Object defaultValue,int maxLength) throws PageException {
1489        param(type, name, defaultValue,Double.NaN,Double.NaN,null,maxLength);
1490    }
1491
1492    public void param(String type, String name, Object defaultValue) throws PageException {
1493        param(type, name, defaultValue,Double.NaN,Double.NaN,null,-1);
1494    }
1495        
1496    private void param(String type, String name, Object defaultValue, double min,double max, String strPattern, int maxLength) throws PageException {
1497
1498        // check attributes type
1499        if(type==null)type="any";
1500                else type=type.trim().toLowerCase();
1501
1502        // check attributes name
1503        if(StringUtil.isEmpty(name))
1504                        throw new ExpressionException("The attribute name is required");
1505        
1506        Object value=null;
1507                boolean isNew=false;
1508                
1509                // get value
1510                value=VariableInterpreter.getVariableEL(this,name,NullSupportHelper.NULL());
1511                if(NullSupportHelper.NULL()==value) {
1512                        if(defaultValue==null)
1513                                throw new ExpressionException("The required parameter ["+name+"] was not provided.");
1514                        value=defaultValue;
1515                        isNew=true;
1516                }
1517                
1518                // cast and set value
1519                if(!"any".equals(type)) {
1520                        // range
1521                        if("range".equals(type)) {
1522                                boolean hasMin=Decision.isValid(min);
1523                                boolean hasMax=Decision.isValid(max);
1524                                double number = Caster.toDoubleValue(value);
1525                                
1526                                if(!hasMin && !hasMax)
1527                                        throw new ExpressionException("you need to define one of the following attributes [min,max], when type is set to [range]");
1528                                
1529                                if(hasMin && number<min)
1530                                        throw new ExpressionException("The number ["+Caster.toString(number)+"] is to small, the number must be at least ["+Caster.toString(min)+"]");
1531                                
1532                                if(hasMax && number>max)
1533                                        throw new ExpressionException("The number ["+Caster.toString(number)+"] is to big, the number cannot be bigger than ["+Caster.toString(max)+"]");
1534                                
1535                                setVariable(name,Caster.toDouble(number));
1536                        }
1537                        // regex
1538                        else if("regex".equals(type) || "regular_expression".equals(type)) {
1539                                String str=Caster.toString(value);
1540                                
1541                                if(strPattern==null) throw new ExpressionException("Missing attribute [pattern]");
1542                                
1543                                try {
1544                                        Pattern pattern = new Perl5Compiler().compile(strPattern, Perl5Compiler.DEFAULT_MASK);
1545                                PatternMatcherInput input = new PatternMatcherInput(str);
1546                                if( !new Perl5Matcher().matches(input, pattern))
1547                                        throw new ExpressionException("The value ["+str+"] doesn't match the provided pattern ["+strPattern+"]");
1548                                
1549                                } catch (MalformedPatternException e) {
1550                                        throw new ExpressionException("The provided pattern ["+strPattern+"] is invalid",e.getMessage());
1551                                }
1552                                setVariable(name,str);
1553                        }
1554                        else if ( type.equals( "int" ) || type.equals( "integer" ) ) {
1555
1556                                if ( !Decision.isInteger( value ) )
1557                                        throw new ExpressionException( "The value [" + value + "] is not a valid integer" );
1558
1559                setVariable( name, value );
1560                        }
1561                        else {
1562                                if(!Decision.isCastableTo(type,value,true,true,maxLength)) {
1563                                        if(maxLength>-1 && ("email".equalsIgnoreCase(type) || "url".equalsIgnoreCase(type) || "string".equalsIgnoreCase(type))) {
1564                                                StringBuilder msg=new StringBuilder(CasterException.createMessage(value, type));
1565                                                msg.append(" with a maximum length of "+maxLength+" characters");
1566                                                throw new CasterException(msg.toString());      
1567                                        }
1568                                        throw new CasterException(value,type);  
1569                                }
1570                                
1571                                setVariable(name,value);
1572                                //REALCAST setVariable(name,Caster.castTo(this,type,value,true));
1573                        }
1574                }
1575            else if(isNew) setVariable(name,value);
1576        }
1577
1578
1579    @Override
1580    public Object removeVariable(String var) throws PageException {
1581                return VariableInterpreter.removeVariable(this,var);
1582        }
1583
1584    /**
1585     * a variable reference, references to variable, to modifed it, with global effect.
1586     * @param var variable name to get
1587     * @return return a variable reference by string syntax ("scopename.key.key" -> "url.name")
1588     * @throws PageException
1589     */
1590    public VariableReference getVariableReference(String var) throws PageException { 
1591            return VariableInterpreter.getVariableReference(this,var);
1592        } 
1593        
1594    @Override
1595    public Object getFunction(Object coll, String key, Object[] args) throws PageException {
1596        return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args);
1597        }
1598
1599        @Override
1600        public Object getFunction(Object coll, Key key, Object[] args) throws PageException {
1601                return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args);
1602        }
1603        
1604    @Override
1605    public Object getFunctionWithNamedValues(Object coll, String key, Object[] args) throws PageException {
1606                return variableUtil.callFunctionWithNamedValues(this,coll,key,args);
1607        }
1608
1609        @Override
1610        public Object getFunctionWithNamedValues(Object coll, Key key, Object[] args) throws PageException {
1611                return variableUtil.callFunctionWithNamedValues(this,coll,key,args);
1612        }
1613
1614    @Override
1615    public ConfigWeb getConfig() {
1616        return config;
1617    }
1618    
1619    @Override
1620    public Iterator getIterator(String key) throws PageException {
1621                Object o=VariableInterpreter.getVariable(this,key);
1622                if(o instanceof Iterator) return (Iterator) o;
1623                throw new ExpressionException("["+key+"] is not a iterator object");
1624        }
1625
1626    @Override
1627    public Query getQuery(String key) throws PageException {
1628                Object value=VariableInterpreter.getVariable(this,key);
1629                if(Decision.isQuery(value)) return Caster.toQuery(value);
1630        throw new CasterException(value,Query.class);///("["+key+"] is not a query object, object is from type ");
1631        }
1632    
1633    @Override
1634    public Query getQuery(Object value) throws PageException {
1635        if(Decision.isQuery(value)) return Caster.toQuery(value);
1636        value=VariableInterpreter.getVariable(this,Caster.toString(value));
1637        if(Decision.isQuery(value)) return Caster.toQuery(value);
1638        throw new CasterException(value,Query.class);
1639        }
1640
1641        @Override
1642        public void setAttribute(String name, Object value) {
1643            try {
1644            if(value==null)removeVariable(name);
1645            else setVariable(name,value);
1646        } catch (PageException e) {}
1647        }
1648
1649        @Override
1650        public void setAttribute(String name, Object value, int scope) {
1651                switch(scope){
1652                case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
1653                        if(value==null) getServletContext().removeAttribute(name);
1654                        else getServletContext().setAttribute(name, value);
1655                break;
1656                case javax.servlet.jsp.PageContext.PAGE_SCOPE:
1657                        setAttribute(name, value);
1658                break;
1659                case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
1660                        if(value==null) req.removeAttribute(name);
1661                        else setAttribute(name, value);
1662                break;
1663                case javax.servlet.jsp.PageContext.SESSION_SCOPE:
1664                        HttpSession s = req.getSession(true);
1665                        if(value==null)s.removeAttribute(name);
1666                        else s.setAttribute(name, value);
1667                break;
1668                }       
1669        }
1670
1671        @Override
1672        public Object getAttribute(String name) {
1673                try {
1674                        return getVariable(name);
1675                } catch (PageException e) {
1676                        return null;
1677                }
1678        }
1679
1680        @Override
1681        public Object getAttribute(String name, int scope) {
1682                switch(scope){
1683                case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
1684                        return getServletContext().getAttribute(name);
1685                case javax.servlet.jsp.PageContext.PAGE_SCOPE:
1686                        return getAttribute(name);
1687                case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
1688                        return req.getAttribute(name);
1689                case javax.servlet.jsp.PageContext.SESSION_SCOPE:
1690                        HttpSession s = req.getSession();
1691                        if(s!=null)return s.getAttribute(name);
1692                break;
1693                }       
1694                return null;
1695        }
1696
1697        @Override
1698        public Object findAttribute(String name) {
1699                // page
1700                Object value=getAttribute(name);
1701                if(value!=null) return value;
1702                // request
1703                value=req.getAttribute(name);
1704                if(value!=null) return value;
1705                // session
1706                HttpSession s = req.getSession();
1707                value=s!=null?s.getAttribute(name):null;
1708                if(value!=null) return value;
1709                // application
1710                value=getServletContext().getAttribute(name);
1711                if(value!=null) return value;
1712                
1713                
1714                return null;
1715        }
1716
1717        @Override
1718        public void removeAttribute(String name) {
1719                setAttribute(name, null);
1720        }
1721
1722        @Override
1723        public void removeAttribute(String name, int scope) {
1724                setAttribute(name, null,scope);
1725        }
1726
1727        @Override
1728        public int getAttributesScope(String name) {
1729                // page
1730                if(getAttribute(name)!=null) return PageContext.PAGE_SCOPE;
1731        // request
1732        if(req.getAttribute(name) != null) return PageContext.REQUEST_SCOPE;
1733        // session
1734        HttpSession s = req.getSession();
1735        if(s!=null && s.getAttribute(name) != null) return PageContext.SESSION_SCOPE;
1736        // application
1737        if(getServletContext().getAttribute(name)!=null) return PageContext.APPLICATION_SCOPE;
1738        
1739                return 0;
1740        }
1741
1742        @Override
1743        public Enumeration getAttributeNamesInScope(int scope) {
1744                
1745        switch(scope){
1746                case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
1747                        return getServletContext().getAttributeNames();
1748                case javax.servlet.jsp.PageContext.PAGE_SCOPE:
1749                        return ItAsEnum.toStringEnumeration(variablesScope().keyIterator());
1750                case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
1751                        return req.getAttributeNames();
1752                case javax.servlet.jsp.PageContext.SESSION_SCOPE:
1753                        return req.getSession(true).getAttributeNames();
1754                }
1755                return null;
1756        }
1757
1758        @Override
1759        public JspWriter getOut() {
1760                return forceWriter;
1761        }
1762
1763        @Override
1764        public HttpSession getSession() {
1765                return getHttpServletRequest().getSession();
1766        }
1767
1768        @Override
1769        public Object getPage() {
1770                return variablesScope();
1771        }
1772
1773        @Override
1774        public ServletRequest getRequest() {
1775                return getHttpServletRequest();
1776        }
1777        
1778    @Override
1779    public HttpServletRequest getHttpServletRequest() {
1780                return req;
1781        }
1782
1783        @Override
1784        public ServletResponse getResponse() {
1785                return rsp;
1786        }
1787
1788    @Override
1789    public HttpServletResponse getHttpServletResponse() {
1790                return rsp;
1791        }
1792    
1793    public OutputStream getResponseStream() throws IOException {
1794        return getRootOut().getResponseStream();
1795        }
1796
1797        @Override
1798        public Exception getException() {
1799                // TODO impl
1800                return exception;
1801        }
1802
1803        @Override
1804        public ServletConfig getServletConfig() {
1805                return config;
1806        }
1807
1808        @Override
1809        public ServletContext getServletContext() {
1810                return servlet.getServletContext();
1811        }
1812
1813        /*public static void main(String[] args) {
1814                repl(" susi #error.susi# sorglos","susi", "Susanne");
1815                repl(" susi #error.Susi# sorglos","susi", "Susanne");
1816        }*/
1817        private static String repl(String haystack, String needle, String replacement) {
1818                //print.o("------------");
1819                //print.o(haystack);
1820                //print.o(needle);
1821                StringBuilder regex=new StringBuilder("#[\\s]*error[\\s]*\\.[\\s]*");
1822                
1823                char[] carr = needle.toCharArray();
1824                for(int i=0;i<carr.length;i++){
1825                        regex.append("[");
1826                        regex.append(Character.toLowerCase(carr[i]));
1827                        regex.append(Character.toUpperCase(carr[i]));
1828                        regex.append("]");
1829                }
1830                
1831                
1832                regex.append("[\\s]*#");
1833                //print.o(regex);
1834                
1835                
1836                haystack=haystack.replaceAll(regex.toString(), replacement);
1837                //print.o(haystack);
1838                return haystack;
1839        }
1840        
1841        
1842        @Override
1843        public void handlePageException(PageException pe) {
1844                if(!Abort.isSilentAbort(pe)) {
1845                        if(requestTimeoutException!=null)
1846                                pe=Caster.toPageException(requestTimeoutException);
1847                        
1848                        
1849                        Charset cs = ReqRspUtil.getCharacterEncoding(this,rsp);
1850                if(cs==null) {
1851                                rsp.setContentType("text/html");
1852                }
1853                else {
1854                        rsp.setContentType("text/html; charset=" + cs.name());
1855                }
1856                if(pe instanceof PageExceptionImpl && ((PageExceptionImpl)pe).getExposeMessage())
1857                        rsp.setHeader("exception-message", StringUtil.emptyIfNull(pe.getMessage()).replace('\n', ' '));
1858                //rsp.setHeader("exception-detail", pe.getDetail());
1859                
1860                        int statusCode=getStatusCode(pe);
1861                        
1862                        if(getConfig().getErrorStatusCode())rsp.setStatus(statusCode);
1863                        
1864                        ErrorPage ep=errorPagePool.getErrorPage(pe,ErrorPageImpl.TYPE_EXCEPTION);
1865                        
1866                        //ExceptionHandler.printStackTrace(this,pe);
1867                        ExceptionHandler.log(getConfig(),pe);
1868
1869                        // error page exception
1870                        if(ep!=null) {
1871                                try {
1872                                        Struct sct=pe.getErrorBlock(this,ep);
1873                                        variablesScope().setEL(KeyConstants._error,sct);
1874                                        variablesScope().setEL(KeyConstants._cferror,sct);
1875                                        
1876                                        doInclude(ep.getTemplate());
1877                                        return;
1878                                } catch (Throwable t) {
1879                                        ExceptionUtil.rethrowIfNecessary(t);
1880                                        if(Abort.isSilentAbort(t)) return;
1881                                        pe=Caster.toPageException(t);
1882                                }
1883                        }
1884                        
1885                        // error page request
1886                        ep=errorPagePool.getErrorPage(pe,ErrorPageImpl.TYPE_REQUEST);
1887                        if(ep!=null) {
1888                                PageSource ps = ep.getTemplate();
1889                                if(ps.physcalExists()){
1890                                        Resource res = ps.getResource();
1891                                        try {
1892                                                String content = IOUtil.toString(res, getConfig().getTemplateCharset());
1893                                                Struct sct=pe.getErrorBlock(this,ep);
1894                                                java.util.Iterator<Entry<Key, Object>> it = sct.entryIterator();
1895                                                Entry<Key, Object> e;
1896                                                String v;
1897                                                while(it.hasNext()){
1898                                                        e = it.next();
1899                                                        v=Caster.toString(e.getValue(),null);
1900                                                        if(v!=null)content=repl(content, e.getKey().getString(), v);
1901                                                }
1902                                                
1903                                                write(content);
1904                                                return;
1905                                        } catch (Throwable t) {
1906                                                pe=Caster.toPageException(t);
1907                                        }
1908                                }
1909                                else pe=new ApplicationException("The error page template for type request only works if the actual source file also exists. If the exception file is in an Lucee archive (lco), you need to use type exception instead.");
1910                        }
1911                        
1912                        try {
1913
1914                                String template=getConfig().getErrorTemplate(statusCode);
1915                                if(!StringUtil.isEmpty(template)) {
1916                                        try {
1917                                                Struct catchBlock=pe.getCatchBlock(getConfig());
1918                                                variablesScope().setEL(KeyConstants._cfcatch,catchBlock);
1919                                                variablesScope().setEL(KeyConstants._catch,catchBlock);
1920                                                doInclude(template);
1921                                            return;
1922                                } 
1923                                        catch (PageException e) {
1924                                                pe=e;
1925                                        }
1926                                }
1927                                if(!Abort.isSilentAbort(pe))forceWrite(getConfig().getDefaultDumpWriter(DumpWriter.DEFAULT_RICH).toString(this,pe.toDumpData(this, 9999,DumpUtil.toDumpProperties()),true));
1928                        } 
1929                        catch (Exception e) {}
1930                }
1931        }
1932
1933        private int getStatusCode(PageException pe) {
1934                int statusCode=500;
1935                int maxDeepFor404=0;
1936                if(pe instanceof ModernAppListenerException){
1937                        pe=((ModernAppListenerException)pe).getPageException();
1938                        maxDeepFor404=1;
1939                }
1940                else if(pe instanceof PageExceptionBox)
1941                        pe=((PageExceptionBox)pe).getPageException();
1942                
1943                if(pe instanceof MissingIncludeException) {
1944                        MissingIncludeException mie=(MissingIncludeException) pe;
1945                        if(mie.getPageDeep()<=maxDeepFor404) statusCode=404;
1946                }
1947                
1948                // TODO Auto-generated method stub
1949                return statusCode;
1950        }
1951
1952
1953        @Override
1954        public void handlePageException(Exception e) {
1955                // DO NOT rethrow ThreadDeath
1956        handlePageException(Caster.toPageException(e));         
1957        }
1958
1959        @Override
1960        public void handlePageException(Throwable t) {
1961                // DO NOT rethrow ThreadDeath
1962        handlePageException(Caster.toPageException(t));
1963        }
1964
1965    @Override
1966    public void setHeader(String name, String value) {
1967                rsp.setHeader(name,value);
1968        }
1969
1970        @Override
1971        public BodyContent pushBody() {
1972        forceWriter=bodyContentStack.push();
1973        if(enablecfoutputonly>0 && outputState==0) {
1974            writer=devNull;
1975        }
1976        else writer=forceWriter;
1977        return (BodyContent)forceWriter;
1978        }
1979
1980        @Override
1981        public JspWriter popBody() {
1982        forceWriter=bodyContentStack.pop();
1983        if(enablecfoutputonly>0 && outputState==0) {
1984            writer=devNull;
1985        }
1986        else writer=forceWriter;
1987        return forceWriter;
1988        }
1989
1990    @Override
1991    public void outputStart() {
1992                outputState++;
1993        if(enablecfoutputonly>0 && outputState==1)writer=forceWriter;
1994                //if(enablecfoutputonly && outputState>0) unsetDevNull();
1995        }
1996
1997    @Override
1998    public void outputEnd() {
1999                outputState--;
2000                if(enablecfoutputonly>0 && outputState==0)writer=devNull;
2001        }
2002
2003    @Override
2004    public void setCFOutputOnly(boolean boolEnablecfoutputonly) {
2005        if(boolEnablecfoutputonly)this.enablecfoutputonly++;
2006        else if(this.enablecfoutputonly>0)this.enablecfoutputonly--;
2007        setCFOutputOnly(enablecfoutputonly);
2008        //if(!boolEnablecfoutputonly)setCFOutputOnly(enablecfoutputonly=0);
2009    }
2010
2011    @Override
2012    public void setCFOutputOnly(short enablecfoutputonly) {
2013        this.enablecfoutputonly=enablecfoutputonly;
2014        if(enablecfoutputonly>0) {
2015            if(outputState==0) writer=devNull;
2016        }
2017        else {
2018            writer=forceWriter;
2019        }
2020    }
2021
2022    @Override
2023    public boolean setSilent() {
2024        boolean before=bodyContentStack.getDevNull();
2025                bodyContentStack.setDevNull(true);
2026                
2027        forceWriter = bodyContentStack.getWriter();
2028        writer=forceWriter;
2029        return before;
2030        }
2031        
2032    @Override
2033    public boolean unsetSilent() {
2034        boolean before=bodyContentStack.getDevNull();
2035        bodyContentStack.setDevNull(false);
2036        
2037        forceWriter = bodyContentStack.getWriter();
2038        if(enablecfoutputonly>0 && outputState==0) {
2039            writer=devNull;
2040        }
2041        else writer=forceWriter;
2042        return before;
2043        }
2044    
2045
2046    @Override
2047    public Debugger getDebugger() {
2048                return debugger;
2049        }
2050    
2051    @Override
2052    public void executeRest(String relPath, boolean throwExcpetion) throws PageException  {
2053        ApplicationListener listener=null;//config.get ApplicationListener();
2054            try{
2055        String pathInfo = req.getPathInfo();
2056        
2057        // charset
2058        try{
2059                String charset=HTTPUtil.splitMimeTypeAndCharset(req.getContentType(),new String[]{"",""})[1];
2060        if(StringUtil.isEmpty(charset))charset=getWebCharset().name();
2061                java.net.URL reqURL = new java.net.URL(req.getRequestURL().toString());
2062                String path=ReqRspUtil.decode(reqURL.getPath(),charset,true);
2063                String srvPath=req.getServletPath();
2064                if(path.startsWith(srvPath)) {
2065                        pathInfo=path.substring(srvPath.length());
2066                }
2067        }
2068        catch (Exception e){}
2069        
2070        
2071        // Service mapping
2072        if(StringUtil.isEmpty(pathInfo) || pathInfo.equals("/")) {// ToDo
2073                // list available services (if enabled in admin)
2074                if(config.getRestList()) {
2075                        try {
2076                                        HttpServletRequest _req = getHttpServletRequest();
2077                                write("Available sevice mappings are:<ul>");
2078                                lucee.runtime.rest.Mapping[] mappings = config.getRestMappings();
2079                                lucee.runtime.rest.Mapping _mapping;
2080                                        String path;
2081                                        for(int i=0;i<mappings.length;i++){
2082                                                _mapping=mappings[i];
2083                                                Resource p = _mapping.getPhysical();
2084                                                path=_req.getContextPath()+ReqRspUtil.getScriptName(this,_req)+_mapping.getVirtual();
2085                                                write("<li "+(p==null || !p.isDirectory()?" style=\"color:red\"":"")+">"+path+"</li>");
2086                                                
2087                                                
2088                                        }
2089                                        write("</ul>");
2090                                        
2091                                } catch (IOException e) {
2092                                        throw Caster.toPageException(e);
2093                                }
2094                }
2095                else 
2096                        RestUtil.setStatus(this, 404, null);
2097                        return;
2098        }       
2099        
2100        // check for matrix
2101        int index;
2102        String entry;
2103        Struct matrix=new StructImpl();
2104        while((index=pathInfo.lastIndexOf(';'))!=-1){
2105                entry=pathInfo.substring(index+1);
2106                pathInfo=pathInfo.substring(0,index);
2107                if(StringUtil.isEmpty(entry,true)) continue;
2108                
2109                index=entry.indexOf('=');
2110                if(index!=-1)matrix.setEL(entry.substring(0,index).trim(), entry.substring(index+1).trim());
2111                else matrix.setEL(entry.trim(), "");
2112        }
2113        
2114        // get accept
2115        List<MimeType> accept = ReqRspUtil.getAccept(this);
2116        MimeType contentType = ReqRspUtil.getContentType(this);
2117        
2118        // check for format extension
2119        //int format = getApplicationContext().getRestSettings().getReturnFormat();
2120        int format;
2121        boolean hasFormatExtension=false;
2122        if(StringUtil.endsWithIgnoreCase(pathInfo, ".json")) {
2123                pathInfo=pathInfo.substring(0,pathInfo.length()-5);
2124                format = UDF.RETURN_FORMAT_JSON;
2125                accept.clear();
2126                accept.add(MimeType.APPLICATION_JSON);
2127                hasFormatExtension=true;
2128        }
2129        else if(StringUtil.endsWithIgnoreCase(pathInfo, ".wddx")) {
2130                pathInfo=pathInfo.substring(0,pathInfo.length()-5);
2131                format = UDF.RETURN_FORMAT_WDDX;
2132                accept.clear();
2133                accept.add(MimeType.APPLICATION_WDDX);
2134                hasFormatExtension=true;
2135        }
2136        else if(StringUtil.endsWithIgnoreCase(pathInfo, ".cfml")) {
2137                pathInfo=pathInfo.substring(0,pathInfo.length()-5);
2138                format = UDF.RETURN_FORMAT_SERIALIZE;
2139                accept.clear();
2140                accept.add(MimeType.APPLICATION_CFML);
2141                hasFormatExtension=true;
2142        }
2143        else if(StringUtil.endsWithIgnoreCase(pathInfo, ".serialize")) {
2144                pathInfo=pathInfo.substring(0,pathInfo.length()-10);
2145                format = UDF.RETURN_FORMAT_SERIALIZE;
2146                accept.clear();
2147                accept.add(MimeType.APPLICATION_CFML);
2148                hasFormatExtension=true;
2149        }
2150        else if(StringUtil.endsWithIgnoreCase(pathInfo, ".xml")) {
2151                pathInfo=pathInfo.substring(0,pathInfo.length()-4);
2152                format = UDF.RETURN_FORMAT_XML;
2153                accept.clear();
2154                accept.add(MimeType.APPLICATION_XML);
2155                hasFormatExtension=true;
2156        }
2157        else if(StringUtil.endsWithIgnoreCase(pathInfo, ".java")) {
2158                pathInfo=pathInfo.substring(0,pathInfo.length()-5);
2159                format = UDFPlus.RETURN_FORMAT_JAVA;
2160                accept.clear();
2161                accept.add(MimeType.APPLICATION_JAVA);
2162                hasFormatExtension=true;
2163        }
2164        else {
2165                format = getApplicationContext().getRestSettings().getReturnFormat();
2166                //MimeType mt=MimeType.toMimetype(format);
2167                //if(mt!=null)accept.add(mt);
2168        }
2169        
2170        if(accept.size()==0) accept.add(MimeType.ALL);
2171        
2172        // loop all mappings
2173        //lucee.runtime.rest.Result result = null;//config.getRestSource(pathInfo, null);
2174        RestRequestListener rl=null;
2175        lucee.runtime.rest.Mapping[] restMappings = config.getRestMappings();
2176        lucee.runtime.rest.Mapping m,mapping=null,defaultMapping=null;
2177        //String callerPath=null;
2178        if(restMappings!=null)for(int i=0;i<restMappings.length;i++) {
2179            m = restMappings[i];
2180            if(m.isDefault())defaultMapping=m;
2181            if(pathInfo.startsWith(m.getVirtualWithSlash(),0) && m.getPhysical()!=null) {
2182                mapping=m;
2183                //result = m.getResult(this,callerPath=pathInfo.substring(m.getVirtual().length()),format,matrix,null);
2184                rl=new RestRequestListener(m,pathInfo.substring(m.getVirtual().length()),matrix,format,hasFormatExtension,accept,contentType,null);
2185                break;
2186            }
2187        }
2188        
2189        // default mapping
2190        if(mapping==null && defaultMapping!=null && defaultMapping.getPhysical()!=null) {
2191                mapping=defaultMapping;
2192            //result = mapping.getResult(this,callerPath=pathInfo,format,matrix,null);
2193                rl=new RestRequestListener(mapping,pathInfo,matrix,format,hasFormatExtension,accept,contentType,null);
2194        }
2195        
2196        
2197        //base = PageSourceImpl.best(config.getPageSources(this,null,relPath,true,false,true));
2198        
2199        
2200        if(mapping==null || mapping.getPhysical()==null){
2201                RestUtil.setStatus(this,404,"no rest service for ["+pathInfo+"] found");
2202        }
2203        else {
2204                base=config.toPageSource(null, mapping.getPhysical(), null);
2205                listener=((MappingImpl)base.getMapping()).getApplicationListener();
2206            listener.onRequest(this, base,rl);
2207        }
2208        
2209        
2210        
2211        }
2212            catch(Throwable t) {
2213                PageException pe = Caster.toPageException(t);
2214                if(!Abort.isSilentAbort(pe)){
2215                        log(true);
2216                        if(fdEnabled){
2217                                FDSignal.signal(pe, false);
2218                        }
2219                        if(listener==null) {
2220                                if(base==null)listener=config.getApplicationListener();
2221                                else listener=((MappingImpl)base.getMapping()).getApplicationListener();
2222                        }
2223                        listener.onError(this,pe);      
2224                }
2225                else log(false);
2226
2227                if(throwExcpetion) throw pe;
2228            }
2229            finally {
2230                if(enablecfoutputonly>0){
2231                setCFOutputOnly((short)0);
2232            }
2233            base=null;
2234            }
2235    }
2236
2237        @Override
2238    public void execute(String relPath, boolean throwExcpetion) throws PageException  {
2239        execute(relPath, throwExcpetion, true);
2240    }
2241    public void execute(String relPath, boolean throwExcpetion, boolean onlyTopLevel) throws PageException  {
2242        if((config.getScriptProtect()&ApplicationContext.SCRIPT_PROTECT_URL)>0) {
2243                relPath=ScriptProtect.translate(relPath);
2244        }
2245        
2246        //SystemOut.printDate(config.getOutWriter(),"Call:"+relPath+" (id:"+getId()+";running-requests:"+config.getThreadQueue().size()+";)");
2247            if(relPath.startsWith("/mapping-")){
2248                base=null;
2249                int index = relPath.indexOf('/',9);
2250                if(index>-1){
2251                        String type = relPath.substring(9,index);
2252                        if(type.equalsIgnoreCase("tag")){
2253                                base=getPageSource(
2254                                                new Mapping[]{config.getTagMapping(),config.getServerTagMapping()},
2255                                                relPath.substring(index)
2256                                                );
2257                        }
2258                        else if(type.equalsIgnoreCase("customtag")){
2259                                base=getPageSource(
2260                                                config.getCustomTagMappings(),
2261                                                relPath.substring(index)
2262                                                );
2263                        }
2264                        /*else if(type.equalsIgnoreCase("gateway")){
2265                                base=config.getGatewayEngine().getMapping().getPageSource(relPath.substring(index));
2266                                if(!base.exists())base=getPageSource(relPath.substring(index));
2267                        }*/
2268                }
2269                if(base==null) base=PageSourceImpl.best(config.getPageSources(this,null,relPath,onlyTopLevel,false,true));
2270            }
2271            else base=PageSourceImpl.best(config.getPageSources(this,null,relPath,onlyTopLevel,false,true));
2272            ApplicationListener listener=gatewayContext?config.getApplicationListener():((MappingImpl)base.getMapping()).getApplicationListener();
2273            
2274            
2275            try {
2276                listener.onRequest(this,base,null);
2277                log(false);
2278            }
2279            catch(Throwable t) {
2280                PageException pe = Caster.toPageException(t);
2281                if(!Abort.isSilentAbort(pe)){
2282                        this.pe=pe;
2283                        log(true);
2284                        if(fdEnabled){
2285                                FDSignal.signal(pe, false);
2286                        }
2287                        listener.onError(this,pe);
2288                }
2289                else log(false);
2290                if(throwExcpetion) {
2291                        ExceptionUtil.rethrowIfNecessary(t);
2292                        throw pe;
2293                }
2294            }
2295            finally {
2296            if(enablecfoutputonly>0){
2297                setCFOutputOnly((short)0);
2298            }
2299            if(!gatewayContext && getConfig().debug()) {
2300                try {
2301                                        listener.onDebug(this);
2302                                } 
2303                catch (PageException pe) {
2304                        if(!Abort.isSilentAbort(pe))listener.onError(this,pe);
2305                                }
2306            }
2307            base=null;
2308            }
2309        }
2310
2311        private void log(boolean error) {
2312                if(!isGatewayContext() && config.isMonitoringEnabled()) {
2313            RequestMonitor[] monitors = config.getRequestMonitors();
2314            if(monitors!=null)for(int i=0;i<monitors.length;i++){
2315                if(monitors[i].isLogEnabled()){
2316                        try {
2317                                monitors[i].log(this,error);
2318                                } 
2319                                catch (Throwable e) {
2320                                        ExceptionUtil.rethrowIfNecessary(e);
2321                                }
2322                    }
2323            }
2324                }
2325        }
2326
2327        private PageSource getPageSource(Mapping[] mappings, String relPath) {
2328                PageSource ps;
2329                //print.err(mappings.length);
2330        for(int i=0;i<mappings.length;i++) {
2331            ps = mappings[i].getPageSource(relPath);
2332            //print.err(ps.getDisplayPath());
2333            if(ps.exists()) return ps;
2334            
2335        }
2336                return null;
2337        }
2338
2339
2340
2341        @Override
2342        public void include(String relPath) throws ServletException,IOException  {
2343                HTTPUtil.include(this, relPath);
2344        }
2345        
2346
2347        @Override
2348        public void forward(String relPath) throws ServletException, IOException {
2349                HTTPUtil.forward(this, relPath);
2350        }
2351
2352        public void include(PageSource ps) throws ServletException  {
2353                try {
2354                        doInclude(ps);
2355                } catch (PageException pe) {
2356                        throw new PageServletException(pe);
2357                }
2358        }
2359
2360    @Override
2361    public void clear() {
2362                try {
2363                        //print.o(getOut().getClass().getName());
2364                        getOut().clear();
2365                } catch (IOException e) {}
2366        }
2367        
2368    @Override
2369    public long getRequestTimeout() {
2370                if(requestTimeout==-1) {
2371                        if(applicationContext!=null) {
2372                                return (applicationContext).getRequestTimeout().getMillis();
2373                        }
2374                        requestTimeout=config.getRequestTimeout().getMillis();
2375                }
2376                return requestTimeout;
2377        }
2378        
2379    @Override
2380    public void setRequestTimeout(long requestTimeout) {
2381                this.requestTimeout = requestTimeout;
2382        }
2383
2384    @Override
2385    public String getCFID() {
2386                if(cfid==null) initIdAndToken();
2387                return cfid;
2388        }
2389
2390    @Override
2391    public String getCFToken() {
2392                if(cftoken==null) initIdAndToken();
2393                return cftoken;
2394        }
2395
2396    @Override
2397    public String getURLToken() {
2398            if(getConfig().getSessionType()==Config.SESSION_TYPE_J2EE) {
2399                HttpSession s = getSession();
2400                    return "CFID="+getCFID()+"&CFTOKEN="+getCFToken()+"&jsessionid="+(s!=null?getSession().getId():"");
2401                }
2402                return "CFID="+getCFID()+"&CFTOKEN="+getCFToken();
2403        }
2404    
2405    @Override
2406    public String getJSessionId() {
2407            if(getConfig().getSessionType()==Config.SESSION_TYPE_J2EE) {
2408                    return getSession().getId();
2409                }
2410                return null;
2411        }
2412
2413
2414    /**
2415     * initialize the cfid and the cftoken
2416     */
2417    private void initIdAndToken() {
2418        boolean setCookie=true;
2419        // From URL
2420        Object oCfid = urlScope().get(KeyConstants._cfid,null);
2421        Object oCftoken = urlScope().get(KeyConstants._cftoken,null);
2422        
2423        // Cookie
2424        if((oCfid==null || !Decision.isGUIdSimple(oCfid)) || oCftoken==null) {
2425            setCookie=false;
2426            oCfid = cookieScope().get(KeyConstants._cfid,null);
2427            oCftoken = cookieScope().get(KeyConstants._cftoken,null);
2428        }
2429
2430        // check cookie value
2431        if(oCfid!=null) {
2432                // cookie value is invalid, maybe from ACF
2433                if(!Decision.isGUIdSimple(oCfid)) {
2434                        oCfid=null;
2435                        oCftoken=null;
2436                        Charset charset = getWebCharset();
2437                        
2438                        // check if we have multiple cookies with the name "cfid" and a other one is valid
2439                        javax.servlet.http.Cookie[] cookies = getHttpServletRequest().getCookies();
2440                        String name,value;
2441                        if(cookies!=null){
2442                                for(int i=0;i<cookies.length;i++){
2443                                        name=ReqRspUtil.decode(cookies[i].getName(),charset.name(),false);
2444                                        
2445                                        // CFID
2446                                        if("cfid".equalsIgnoreCase(name)) {
2447                                                value=ReqRspUtil.decode(cookies[i].getValue(),charset.name(),false);
2448                                                if(Decision.isGUIdSimple(value)) oCfid=value;
2449                                                ReqRspUtil.removeCookie(getHttpServletResponse(),name);
2450                                        }
2451                                        // CFToken
2452                                        else if("cftoken".equalsIgnoreCase(name)) {
2453                                                value=ReqRspUtil.decode(cookies[i].getValue(),charset.name(),false);
2454                                                if(isValidCfToken(value)) oCftoken=value;
2455                                                ReqRspUtil.removeCookie(getHttpServletResponse(),name);
2456                                        }
2457                                }
2458                        }
2459                        
2460                        if(oCfid!=null) {
2461                                setCookie=true;
2462                                if(oCftoken==null)oCftoken="0";
2463                        }
2464                }
2465        }
2466        // New One
2467        if(oCfid==null || oCftoken==null) {
2468            setCookie=true;
2469            cfid=ScopeContext.getNewCFId();
2470            cftoken=ScopeContext.getNewCFToken();
2471        }
2472        else {
2473            cfid=Caster.toString(oCfid,null);
2474            cftoken=Caster.toString(oCftoken,null);
2475        }
2476        
2477        if(setCookie && applicationContext.isSetClientCookies())
2478                setClientCookies();
2479    }
2480    
2481
2482    private boolean isValidCfToken(String value) {
2483                return Operator.compare(value, "0")==0;
2484        }
2485
2486
2487
2488        public void resetIdAndToken() {
2489        cfid=ScopeContext.getNewCFId();
2490        cftoken=ScopeContext.getNewCFToken();
2491
2492        if(applicationContext.isSetClientCookies())
2493                setClientCookies();
2494    }
2495
2496
2497        private void setClientCookies() {
2498
2499                String domain = PageContextUtil.getCookieDomain( this );
2500                cookieScope().setCookieEL( KeyConstants._cfid, cfid, CookieImpl.NEVER,false, "/", domain, true, true, false );
2501                cookieScope().setCookieEL( KeyConstants._cftoken, cftoken, CookieImpl.NEVER,false, "/", domain, true, true, false );
2502        }
2503    
2504
2505    @Override
2506    public int getId() {
2507                return id;
2508        }
2509
2510    /**
2511     * @return returns the root JSP Writer
2512     * 
2513     */
2514    public CFMLWriter getRootOut() {
2515                return bodyContentStack.getBase();
2516        }
2517    public JspWriter getRootWriter() {
2518                return bodyContentStack.getBase();
2519        }
2520
2521    @Override
2522    public void setPsq(boolean psq) {
2523                this.psq=psq;
2524        }
2525        
2526    @Override
2527    public boolean getPsq() {
2528                return psq;
2529        }
2530
2531    @Override
2532    public Locale getLocale() {
2533        Locale l = ((ApplicationContextPro)getApplicationContext()).getLocale();
2534        if(l!=null) return l;
2535        if(locale!=null) return locale;
2536        return config.getLocale();
2537        }
2538        
2539    @Override
2540    public void setLocale(Locale locale) {
2541                
2542                ((ApplicationContextPro)getApplicationContext()).setLocale(locale);
2543        this.locale=locale;
2544        HttpServletResponse rsp = getHttpServletResponse();
2545        
2546        Charset charEnc = ReqRspUtil.getCharacterEncoding(this,rsp);
2547        rsp.setLocale(locale);
2548        if(charEnc.equals(CharsetUtil.UTF8)) {
2549                rsp.setContentType("text/html; charset=UTF-8");
2550        }
2551        else if(!charEnc.equals(ReqRspUtil.getCharacterEncoding(this,rsp))) {
2552                rsp.setContentType("text/html; charset=" + charEnc);
2553        }
2554        }
2555    
2556
2557    @Override
2558    public void setLocale(String strLocale) throws ExpressionException {
2559                setLocale(Caster.toLocale(strLocale));
2560        }
2561
2562    @Override
2563    public void setErrorPage(ErrorPage ep) {
2564                errorPagePool.setErrorPage(ep);
2565        }
2566    
2567    @Override
2568    public Tag use(Class clazz) throws PageException {
2569        return use(clazz.getName());
2570        }
2571        
2572    @Override
2573    public Tag use(String tagClassName) throws PageException {
2574        return use(tagClassName,null,-1);
2575    }
2576    public Tag use(String tagClassName, String fullname,int attrType) throws PageException {
2577        
2578        parentTag=currentTag;
2579                currentTag= tagHandlerPool.use(tagClassName);
2580        if(currentTag==parentTag) throw new ApplicationException("");
2581        currentTag.setPageContext(this);
2582        currentTag.setParent(parentTag);
2583        if(attrType>=0 && fullname!=null) {
2584                Map<Collection.Key, Object> attrs = (applicationContext).getTagAttributeDefaultValues(fullname);
2585                if(attrs!=null) {
2586                        TagUtil.setAttributes(this,currentTag, attrs, attrType);
2587                }
2588        }
2589        return currentTag;
2590        }
2591        
2592    @Override
2593    public void reuse(Tag tag) throws PageException {
2594        currentTag=tag.getParent();
2595        tagHandlerPool.reuse(tag);
2596        }
2597
2598    @Override
2599    public QueryCache getQueryCache() {
2600        throw new RuntimeException("funciton PageContext.getQueryCache() no longer supported");
2601    }
2602    
2603    @Override
2604    public void initBody(BodyTag bodyTag, int state) throws JspException {
2605        if (state != Tag.EVAL_BODY_INCLUDE) {
2606            bodyTag.setBodyContent(pushBody());
2607            bodyTag.doInitBody();
2608        }
2609    }
2610    
2611    @Override
2612    public void releaseBody(BodyTag bodyTag, int state) {
2613        if(bodyTag instanceof TryCatchFinally) {
2614            ((TryCatchFinally)bodyTag).doFinally();
2615        }
2616        if (state != Tag.EVAL_BODY_INCLUDE)popBody();
2617    }
2618    
2619    /* *
2620     * @return returns the cfml compiler 
2621     * /
2622    public CFMLCompiler getCompiler() {
2623        return compiler;
2624    }*/
2625    
2626    @Override
2627    public void setVariablesScope(Variables variables) {
2628        this.variables=variables;
2629        undefinedScope().setVariableScope(variables);
2630        
2631        if(variables instanceof ClosureScope) {
2632                variables = ((ClosureScope)variables).getVariables();
2633        }
2634        
2635        if(variables instanceof ComponentScope) {
2636                activeComponent=((ComponentScope)variables).getComponent();
2637        }
2638        else {
2639                activeComponent=null;
2640        }
2641    }
2642
2643    @Override
2644    public Component getActiveComponent() {
2645        return activeComponent;
2646    }
2647    
2648    @Override
2649    public Credential getRemoteUser() throws PageException {
2650        if(remoteUser==null) {
2651                Key name = KeyImpl.init(Login.getApplicationName(applicationContext));
2652                    Resource roles = config.getConfigDir().getRealResource("roles");
2653                    
2654                if(applicationContext.getLoginStorage()==Scope.SCOPE_SESSION) {
2655                Object auth = sessionScope().get(name,null);
2656                if(auth!=null) {
2657                    remoteUser=CredentialImpl.decode(auth,roles);
2658                }
2659            }
2660            else if(applicationContext.getLoginStorage()==Scope.SCOPE_COOKIE) {
2661                Object auth = cookieScope().get(name,null);
2662                if(auth!=null) {
2663                    remoteUser=CredentialImpl.decode(auth,roles);
2664                }
2665            }
2666        }
2667        return remoteUser;
2668    }
2669    
2670    @Override
2671    public void clearRemoteUser() {
2672        if(remoteUser!=null)remoteUser=null;
2673        String name=Login.getApplicationName(applicationContext);
2674            
2675        cookieScope().removeEL(KeyImpl.init(name));
2676        try {
2677                        sessionScope().removeEL(KeyImpl.init(name));
2678                } catch (PageException e) {}
2679        
2680    }
2681    
2682    @Override
2683    public void setRemoteUser(Credential remoteUser) {
2684        this.remoteUser = remoteUser;
2685    }
2686    
2687    @Override
2688    public VariableUtil getVariableUtil() {
2689        return variableUtil;
2690    }
2691
2692    @Override
2693    public void throwCatch() throws PageException {
2694        if(exception!=null) throw exception;
2695        throw new ApplicationException("invalid context for tag/script expression rethow");
2696    }
2697
2698    @Override
2699    public PageException setCatch(Throwable t) {
2700                ExceptionUtil.rethrowIfNecessary(t);
2701        if(t==null) {
2702                exception=null;
2703                undefinedScope().removeEL(KeyConstants._cfcatch);
2704        }
2705        else {
2706                exception = Caster.toPageException(t);
2707                undefinedScope().setEL(KeyConstants._cfcatch,exception.getCatchBlock(config));
2708                if(!gatewayContext && config.debug() && config.hasDebugOptions(ConfigImpl.DEBUG_EXCEPTION)) debugger.addException(config,exception);
2709        }
2710        return exception;
2711    }
2712    
2713    public void setCatch(PageException pe) {
2714        exception = pe;
2715        if(pe==null) {
2716                undefinedScope().removeEL(KeyConstants._cfcatch);
2717        }
2718        else {
2719                undefinedScope().setEL(KeyConstants._cfcatch,pe.getCatchBlock(config));
2720                if(!gatewayContext && config.debug() && config.hasDebugOptions(ConfigImpl.DEBUG_EXCEPTION)) debugger.addException(config,exception);
2721        }
2722    }
2723    
2724    public void setCatch(PageException pe,boolean caught, boolean store) {
2725                if(fdEnabled){
2726                FDSignal.signal(pe, caught);
2727        }
2728        exception = pe;
2729        if(store){
2730                if(pe==null) {
2731                        undefinedScope().removeEL(KeyConstants._cfcatch);
2732                }
2733                else {
2734                        undefinedScope().setEL(KeyConstants._cfcatch,pe.getCatchBlock(config));
2735                        if(!gatewayContext && config.debug() && config.hasDebugOptions(ConfigImpl.DEBUG_EXCEPTION)) debugger.addException(config,exception);
2736                }
2737        }
2738    }
2739    
2740    /**
2741     * @return return current catch
2742     */
2743    public PageException getCatch() {
2744        return exception;
2745    }
2746    
2747    @Override
2748    public void clearCatch() {
2749        exception = null;
2750        undefinedScope().removeEL(KeyConstants._cfcatch);
2751    }
2752
2753    @Override
2754    public void addPageSource(PageSource ps, boolean alsoInclude) {
2755        pathList.add(ps);
2756        if(alsoInclude) 
2757            includePathList.add(ps);
2758    }
2759    
2760
2761    public void addPageSource(PageSource ps, PageSource psInc) {
2762        pathList.add(ps);
2763        if(psInc!=null) 
2764            includePathList.add(psInc);
2765    }
2766
2767    @Override
2768    public void removeLastPageSource(boolean alsoInclude) {
2769        if(!pathList.isEmpty())pathList.removeLast();
2770        if(alsoInclude && !includePathList.isEmpty()) 
2771            includePathList.removeLast();
2772    }
2773
2774
2775    public UDF[] getUDFs() {
2776        return udfs.toArray(new UDF[udfs.size()]);
2777    }
2778    
2779    public void addUDF(UDF udf) {
2780        udfs.add(udf);
2781    }
2782
2783    public void removeUDF() {
2784        if(!udfs.isEmpty())udfs.removeLast();
2785    }
2786
2787    @Override
2788    public FTPPool getFTPPool() {
2789        return null;
2790    }
2791    public FTPPoolImpl getFTPPoolImpl() {
2792        return ftpPool;
2793    }
2794
2795    /* *
2796     * @return Returns the manager.
2797     * /
2798    public DataSourceManager getManager() {
2799        return manager;
2800    }*/
2801    
2802    @Override
2803    public ApplicationContext getApplicationContext() {
2804        return applicationContext;
2805    }
2806    
2807    @Override
2808    public void setApplicationContext(ApplicationContext applicationContext) {
2809        
2810        session=null;
2811        application=null;
2812        client=null;
2813        this.applicationContext = (ApplicationContextPro) applicationContext;
2814        
2815        int scriptProtect = applicationContext.getScriptProtect();
2816        
2817        // ScriptProtecting
2818        if(config.mergeFormAndURL()) {
2819                form.setScriptProtecting(applicationContext,
2820                                (scriptProtect&ApplicationContext.SCRIPT_PROTECT_FORM)>0 
2821                                || 
2822                                (scriptProtect&ApplicationContext.SCRIPT_PROTECT_URL)>0);
2823        }
2824        else {
2825            form.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_FORM)>0);
2826            url.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_URL)>0);
2827        }
2828        cookie.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_COOKIE)>0);
2829        
2830        // CGI
2831        cgiR.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_CGI)>0);
2832        cgiRW.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_CGI)>0);
2833        undefined.reinitialize(this);
2834    }
2835    
2836    /**
2837     * @return return  value of method "onApplicationStart" or true
2838     * @throws PageException 
2839     */
2840    public boolean initApplicationContext(ApplicationListener listener) throws PageException {
2841        boolean initSession=false;
2842        //AppListenerSupport listener = (AppListenerSupport) config.get ApplicationListener();
2843        KeyLock<String> lock = config.getContextLock();
2844        String name=StringUtil.emptyIfNull(applicationContext.getName());
2845        String token=name+":"+getCFID();
2846        
2847        Lock tokenLock = lock.lock(token,getRequestTimeout());
2848        //print.o("outer-lock  :"+token);
2849        try {
2850                // check session before executing any code
2851                initSession=applicationContext.isSetSessionManagement() && listener.hasOnSessionStart(this) && !scopeContext.hasExistingSessionScope(this);
2852                
2853                // init application
2854                
2855                Lock nameLock = lock.lock(name,getRequestTimeout());
2856                //print.o("inner-lock  :"+token);
2857                try {
2858                        RefBoolean isNew=new RefBooleanImpl(false);
2859                            application=scopeContext.getApplicationScope(this,isNew);// this is needed that the application scope is initilized
2860                        if(isNew.toBooleanValue()) {
2861                                    try {
2862                                                if(!listener.onApplicationStart(this)) {
2863                                                        scopeContext.removeApplicationScope(this);
2864                                                    return false;
2865                                                }
2866                                        } catch (PageException pe) {
2867                                                scopeContext.removeApplicationScope(this);
2868                                                throw pe;
2869                                        }
2870                            }
2871                }
2872                finally{
2873                        //print.o("inner-unlock:"+token);
2874                        lock.unlock(nameLock);
2875                }
2876        
2877                // init session
2878                    if(initSession) {
2879                        scopeContext.getSessionScope(this, DUMMY_BOOL);// this is needed that the session scope is initilized
2880                        listener.onSessionStart(this);
2881                        }
2882        }
2883        finally{
2884                //print.o("outer-unlock:"+token);
2885                lock.unlock(tokenLock);
2886        }
2887            return true;
2888    }
2889    
2890
2891    /**
2892     * @return the scope factory
2893     */
2894    public ScopeFactory getScopeFactory() {
2895        return scopeFactory;
2896    }
2897
2898    
2899    
2900    
2901    @Override
2902    public Tag getCurrentTag() {
2903        return currentTag;
2904    }
2905
2906    @Override
2907    public long getStartTime() {
2908        return startTime;
2909    }
2910    
2911    @Override
2912    public Thread getThread() {
2913        return thread;
2914    }
2915    
2916
2917
2918        public void setThread(Thread thread) {
2919                this.thread=thread;
2920        }
2921
2922        // FUTURE add as long
2923    @Override
2924    public int getExecutionTime() {
2925        return (int)executionTime;
2926    }
2927    
2928    public long getExecutionTimeLong() {
2929        return executionTime;
2930    }
2931
2932    @Override
2933    public void setExecutionTime(int executionTime) {
2934        this.executionTime = executionTime;
2935    }
2936    
2937    public void setExecutionTimeLong(long executionTime) {
2938        this.executionTime = executionTime;
2939    }
2940
2941    @Override
2942    public synchronized void compile(PageSource pageSource) throws PageException {
2943        Resource classRootDir = pageSource.getMapping().getClassRootDirectory();
2944        
2945        try {
2946            config.getCompiler().compile(
2947                    config,
2948                    pageSource,
2949                    config.getTLDs(),
2950                    config.getFLDs(),
2951                    classRootDir,
2952                    pageSource.getJavaName()
2953                    );
2954        } catch (Exception e) {
2955            throw Caster.toPageException(e);
2956        }        
2957    }
2958
2959    @Override
2960    public void compile(String relPath) throws PageException {
2961        SystemOut.printDate("method PageContext.compile(String) should no longer be used!");
2962        compile(PageSourceImpl.best(getRelativePageSources(relPath)));
2963    }
2964    
2965    public HttpServlet getServlet() {
2966        return servlet;
2967    }
2968
2969    @Override
2970    public lucee.runtime.Component loadComponent(String compPath) throws PageException {
2971        return ComponentLoader.loadComponent(this,null,compPath,null,null);
2972    }
2973
2974        /**
2975         * @return the base
2976         */
2977        public PageSource getBase() {
2978                return base;
2979        }
2980
2981        /**
2982         * @param base the base to set
2983         */
2984        public void setBase(PageSource base) {
2985                this.base = base;
2986        }
2987
2988        /**
2989         * @return the isCFCRequest
2990         */
2991        public boolean isCFCRequest() {
2992                return isCFCRequest;
2993        }
2994        
2995        @Override
2996        public DataSourceManager getDataSourceManager() {
2997                return manager;
2998        }
2999
3000        @Override
3001        public Object evaluate(String expression) throws PageException {
3002                return new CFMLExpressionInterpreter(false).interpret(this,expression);
3003        }
3004        
3005        @Override
3006        public String serialize(Object expression) throws PageException {
3007                return Serialize.call(this, expression);
3008        }
3009
3010        /**
3011         * @return the activeUDF
3012         */
3013        public UDF getActiveUDF() {
3014                return activeUDF;
3015        }
3016        public Collection.Key getActiveUDFCalledName() {
3017                return activeUDFCalledName;
3018        }
3019        public void setActiveUDFCalledName(Collection.Key activeUDFCalledName) {
3020                this.activeUDFCalledName=activeUDFCalledName;
3021        }
3022
3023        /**
3024         * @param activeUDF the activeUDF to set
3025         */
3026        public void setActiveUDF(UDF activeUDF) {
3027                this.activeUDF = activeUDF;
3028        }
3029
3030        @Override
3031        public CFMLFactory getCFMLFactory() {
3032                return config.getFactory();
3033        }
3034
3035        @Override
3036        public PageContext getParentPageContext() {
3037                return parent;
3038        }
3039
3040
3041        @Override
3042        public String[] getThreadScopeNames() {
3043                if(threads==null)return new String[0];
3044                return CollectionUtil.keysAsString(threads);
3045                //Set ks = threads.keySet();
3046                //return (String[]) ks.toArray(new String[ks.size()]);
3047        }
3048        
3049        @Override
3050        public Threads getThreadScope(String name) {
3051                return getThreadScope(KeyImpl.init(name));
3052        }
3053        
3054        public Threads getThreadScope(Collection.Key name) {
3055                if(threads==null)threads=new StructImpl();
3056                Object obj = threads.get(name,null);
3057                if(obj instanceof Threads)return (Threads) obj;
3058                return null;
3059        }
3060        
3061        public Object getThreadScope(Collection.Key name,Object defaultValue) {
3062                if(threads==null)threads=new StructImpl();
3063                if(name.equalsIgnoreCase(KeyConstants._cfthread)) return threads;
3064                return threads.get(name,defaultValue);
3065        }
3066        
3067        public Object getThreadScope(String name,Object defaultValue) {
3068                if(threads==null)threads=new StructImpl();
3069                if(name.equalsIgnoreCase(KeyConstants._cfthread.getLowerString())) return threads;
3070                return threads.get(KeyImpl.init(name),defaultValue);
3071        }
3072
3073        @Override
3074        public void setThreadScope(String name,Threads ct) {
3075                hasFamily=true;
3076                if(threads==null)       threads=new StructImpl();
3077                threads.setEL(KeyImpl.init(name), ct);
3078        }
3079        
3080        public void setThreadScope(Collection.Key name,Threads ct) {
3081                hasFamily=true;
3082                if(threads==null)       threads=new StructImpl();
3083                threads.setEL(name, ct);
3084        }
3085
3086        @Override
3087        public boolean hasFamily() {
3088                return hasFamily;
3089        }
3090        
3091
3092        public DatasourceConnection _getConnection(String datasource, String user,String pass) throws PageException {
3093                return _getConnection(config.getDataSource(datasource),user,pass);
3094        }
3095        
3096        public DatasourceConnection _getConnection(DataSource ds, String user,String pass) throws PageException {
3097                
3098                String id=DatasourceConnectionPool.createId(ds,user,pass);
3099                DatasourceConnection dc=transConns.get(id);
3100                if(dc!=null && DatasourceConnectionPool.isValid(dc,null)){
3101                        return dc;
3102                }
3103                dc=config.getDatasourceConnectionPool().getDatasourceConnection(ds, user, pass);
3104                transConns.put(id, dc);
3105                return dc;
3106        }
3107
3108        @Override
3109        public TimeZone getTimeZone() {
3110                TimeZone tz = ((ApplicationContextPro)getApplicationContext()).getTimeZone();
3111                if(tz!=null) return tz;
3112                if(timeZone!=null) return timeZone;
3113                return config.getTimeZone();
3114        }
3115        
3116        @Override
3117        public void setTimeZone(TimeZone timeZone) {
3118                ((ApplicationContextPro)getApplicationContext()).setTimeZone(timeZone);
3119                this.timeZone=timeZone;
3120        }
3121
3122
3123        /**
3124         * @return the requestId
3125         */
3126        public int getRequestId() {
3127                return requestId;
3128        }
3129
3130        private Set<String> pagesUsed=new HashSet<String>();
3131
3132        private Stack<ActiveQuery> activeQueries=new Stack<ActiveQuery>();
3133        private Stack<ActiveLock> activeLocks=new Stack<ActiveLock>();
3134
3135        public boolean isTrusted(Page page) {
3136                if(page==null)return false;
3137                
3138                short it = ((MappingImpl)page.getPageSource().getMapping()).getInspectTemplate();
3139                if(it==ConfigImpl.INSPECT_NEVER)return true;
3140                if(it==ConfigImpl.INSPECT_ALWAYS)return false;
3141                
3142                return pagesUsed.contains(""+page.hashCode());
3143        }
3144        
3145        public void setPageUsed(Page page) {
3146                pagesUsed.add(""+page.hashCode());
3147        }
3148
3149        @Override
3150        public void exeLogStart(int position,String id){
3151                if(execLog!=null)execLog.start(position, id);
3152        }
3153        
3154        @Override
3155        public void exeLogEnd(int position,String id){
3156                if(execLog!=null)execLog.end(position, id);
3157        }
3158
3159        
3160        /**
3161         * @param create if set to true, lucee creates a session when not exist
3162         * @return
3163         * @throws PageException
3164         */
3165        public ORMSession getORMSession(boolean create) throws PageException {
3166                
3167                if(ormSession==null || !ormSession.isValid())   {
3168                        if(!create) return null;
3169                        ormSession=config.getORMEngine(this).createSession(this);
3170                }
3171                DatasourceManagerImpl manager = (DatasourceManagerImpl) getDataSourceManager();
3172                manager.add(this,ormSession);
3173                
3174                return ormSession;
3175        }
3176
3177        public ClassLoader getClassLoader() throws IOException {
3178                return getResourceClassLoader();
3179        }
3180        
3181        public ClassLoader getClassLoader(Resource[] reses) throws IOException{
3182                return getResourceClassLoader().getCustomResourceClassLoader(reses);
3183        }
3184        
3185        private ResourceClassLoader getResourceClassLoader() throws IOException {
3186                JavaSettingsImpl js = (JavaSettingsImpl) applicationContext.getJavaSettings();
3187                if(js!=null) {
3188                        return config.getResourceClassLoader().getCustomResourceClassLoader(js.getResourcesTranslated());
3189                }
3190                return config.getResourceClassLoader();
3191        }
3192
3193        public ClassLoader getRPCClassLoader(boolean reload) throws IOException {
3194                JavaSettingsImpl js = (JavaSettingsImpl) applicationContext.getJavaSettings();
3195                if(js!=null) {
3196                        return ((PhysicalClassLoader)config.getRPCClassLoader(reload)).getCustomClassLoader(js.getResourcesTranslated(),reload);
3197                }
3198                return config.getRPCClassLoader(reload);
3199        }
3200        
3201        
3202
3203        public void resetSession() {
3204                this.session=null;
3205        }
3206        /**
3207         * @return the gatewayContext
3208         */
3209        public boolean isGatewayContext() {
3210                return gatewayContext;
3211        }
3212
3213
3214
3215        /**
3216         * @param gatewayContext the gatewayContext to set
3217         */
3218        public void setGatewayContext(boolean gatewayContext) {
3219                this.gatewayContext = gatewayContext;
3220        }
3221
3222
3223
3224        public void setServerPassword(String serverPassword) {
3225                this.serverPassword=serverPassword;
3226        }
3227        public String getServerPassword() {
3228                return serverPassword;
3229        }
3230
3231        public short getSessionType() {
3232                if(isGatewayContext())return Config.SESSION_TYPE_CFML;
3233                return applicationContext.getSessionType();
3234        }
3235        
3236        // this is just a wrapper method for ACF
3237        public Scope SymTab_findBuiltinScope(String name) throws PageException {
3238                return scope(name, null);
3239        }
3240        
3241// FUTURE add to PageContext
3242        public DataSource getDataSource(String datasource) throws PageException {
3243                DataSource ds = ((ApplicationContextPro)getApplicationContext()).getDataSource(datasource,null);
3244                if(ds!=null) return ds;
3245                ds=getConfig().getDataSource(datasource,null);
3246                if(ds!=null) return ds;
3247                
3248                throw DatabaseException.notFoundException(this, datasource);
3249        }
3250                
3251// FUTURE add to PageContext
3252        public DataSource getDataSource(String datasource, DataSource defaultValue) {
3253                DataSource ds = ((ApplicationContextPro)getApplicationContext()).getDataSource(datasource,null);
3254                if(ds==null) ds=getConfig().getDataSource(datasource,defaultValue);
3255                return ds;
3256        }
3257
3258        public void setActiveQuery(ActiveQuery activeQuery) {
3259                this.activeQueries.add(activeQuery);
3260        }
3261        
3262        public ActiveQuery[] getActiveQueries() {
3263                return activeQueries.toArray(new ActiveQuery[activeQueries.size()]);
3264        }
3265
3266        public ActiveQuery releaseActiveQuery() {
3267                return activeQueries.pop();
3268        }
3269
3270        public void setActiveLock(ActiveLock activeLock) {
3271                this.activeLocks.add(activeLock);
3272        }
3273        
3274        public ActiveLock[] getActiveLocks() {
3275                return activeLocks.toArray(new ActiveLock[activeLocks.size()]);
3276        }
3277
3278        public ActiveLock releaseActiveLock() {
3279                return activeLocks.pop();
3280        }
3281
3282        public PageException getPageException() {
3283                return pe;
3284        }
3285
3286        // FUTURE add this methods to the loader
3287        public Charset getResourceCharset() {
3288                Charset cs = ((ApplicationContextPro)getApplicationContext()).getResourceCharset();
3289                if(cs!=null) return cs;
3290                return config._getResourceCharset();
3291        }
3292
3293        public Charset getWebCharset() {
3294                Charset cs = ((ApplicationContextPro)getApplicationContext()).getWebCharset();
3295                if(cs!=null) return cs;
3296                return config._getWebCharset();
3297        }
3298
3299        public short getScopeCascadingType() {
3300                ApplicationContextPro ac = ((ApplicationContextPro)getApplicationContext());
3301                if(ac==null) return config.getScopeCascadingType();
3302                return ac.getScopeCascading();
3303        }
3304
3305        public boolean getTypeChecking() {
3306                ApplicationContextPro ac = ((ApplicationContextPro)getApplicationContext());
3307                if(ac==null) return config.getTypeChecking();
3308                return ac.getTypeChecking();
3309        }
3310
3311
3312
3313        public boolean getAllowCompression() {
3314                ApplicationContextPro ac = ((ApplicationContextPro)getApplicationContext());
3315                if(ac==null) return config.allowCompression();
3316                return ac.getAllowCompression();
3317        }
3318
3319        public boolean getSuppressContent() {
3320                ApplicationContextPro ac = ((ApplicationContextPro)getApplicationContext());
3321                if(ac==null) return config.isSuppressContent();
3322                return ac.getSuppressContent();
3323        }
3324        
3325
3326        public void registerLazyStatement(Statement s) {
3327                if(lazyStats==null)lazyStats=new ArrayList<Statement>();
3328                lazyStats.add(s);
3329        }
3330
3331
3332
3333        public void setAppListenerType(int appListenerType) {
3334                this.appListenerType=appListenerType;
3335        }
3336        public int getAppListenerType() {
3337                return appListenerType;
3338        }
3339
3340
3341
3342        public void setTimestampWithTSOffset(boolean literalTimestampWithTSOffset) {
3343                this.literalTimestampWithTSOffset=literalTimestampWithTSOffset;
3344        }
3345        
3346        public boolean getTimestampWithTSOffset() {
3347                return literalTimestampWithTSOffset;
3348        }
3349
3350
3351}