/**
* Copyright (c) 2014, the Railo Company Ltd.
* Copyright (c) 2015, Lucee Assosication Switzerland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.runtime;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
import java.util.TimeZone;
import javax.el.ELContext;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.el.ExpressionEvaluator;
import javax.servlet.jsp.el.VariableResolver;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TryCatchFinally;
import lucee.commons.db.DBUtil;
import lucee.commons.io.BodyContentStack;
import lucee.commons.io.CharsetUtil;
import lucee.commons.io.IOUtil;
import lucee.commons.io.cache.exp.CacheException;
import lucee.commons.io.log.Log;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.util.ResourceClassLoader;
import lucee.commons.lang.ExceptionUtil;
import lucee.commons.lang.PhysicalClassLoader;
import lucee.commons.lang.StringUtil;
import lucee.commons.lang.SystemOut;
import lucee.commons.lang.mimetype.MimeType;
import lucee.commons.lang.types.RefBoolean;
import lucee.commons.lang.types.RefBooleanImpl;
import lucee.commons.lock.KeyLock;
import lucee.commons.lock.Lock;
import lucee.commons.net.HTTPUtil;
import lucee.intergral.fusiondebug.server.FDSignal;
import lucee.loader.engine.CFMLEngine;
import lucee.runtime.cache.CacheConnection;
import lucee.runtime.cache.CacheUtil;
import lucee.runtime.cache.tag.CacheHandler;
import lucee.runtime.cache.tag.CacheHandlerCollectionImpl;
import lucee.runtime.cache.tag.CacheItem;
import lucee.runtime.cache.tag.include.IncludeCacheItem;
import lucee.runtime.component.ComponentLoader;
import lucee.runtime.config.Config;
import lucee.runtime.config.ConfigImpl;
import lucee.runtime.config.ConfigWeb;
import lucee.runtime.config.ConfigWebImpl;
import lucee.runtime.config.Constants;
import lucee.runtime.config.NullSupportHelper;
import lucee.runtime.config.Password;
import lucee.runtime.db.DataSource;
import lucee.runtime.db.DataSourceManager;
import lucee.runtime.db.DatasourceManagerImpl;
import lucee.runtime.debug.ActiveLock;
import lucee.runtime.debug.ActiveQuery;
import lucee.runtime.debug.DebugCFMLWriter;
import lucee.runtime.debug.DebugEntryTemplate;
import lucee.runtime.debug.Debugger;
import lucee.runtime.debug.DebuggerImpl;
import lucee.runtime.dump.DumpUtil;
import lucee.runtime.dump.DumpWriter;
import lucee.runtime.engine.ExecutionLog;
import lucee.runtime.err.ErrorPage;
import lucee.runtime.err.ErrorPageImpl;
import lucee.runtime.err.ErrorPagePool;
import lucee.runtime.exp.Abort;
import lucee.runtime.exp.ApplicationException;
import lucee.runtime.exp.CasterException;
import lucee.runtime.exp.DatabaseException;
import lucee.runtime.exp.ExceptionHandler;
import lucee.runtime.exp.ExpressionException;
import lucee.runtime.exp.MissingIncludeException;
import lucee.runtime.exp.NoLongerSupported;
import lucee.runtime.exp.PageException;
import lucee.runtime.exp.PageExceptionBox;
import lucee.runtime.exp.RequestTimeoutException;
import lucee.runtime.functions.dynamicEvaluation.Serialize;
import lucee.runtime.functions.owasp.ESAPIEncode;
import lucee.runtime.interpreter.CFMLExpressionInterpreter;
import lucee.runtime.interpreter.VariableInterpreter;
import lucee.runtime.listener.ApplicationContext;
import lucee.runtime.listener.ApplicationContextSupport;
import lucee.runtime.listener.ApplicationListener;
import lucee.runtime.listener.ClassicApplicationContext;
import lucee.runtime.listener.JavaSettingsImpl;
import lucee.runtime.listener.ModernAppListener;
import lucee.runtime.listener.ModernAppListenerException;
import lucee.runtime.listener.SessionCookieData;
import lucee.runtime.listener.SessionCookieDataImpl;
import lucee.runtime.monitor.RequestMonitor;
import lucee.runtime.monitor.RequestMonitorPro;
import lucee.runtime.net.ftp.FTPPoolImpl;
import lucee.runtime.net.http.HTTPServletRequestWrap;
import lucee.runtime.net.http.ReqRspUtil;
import lucee.runtime.net.mail.ServerImpl;
import lucee.runtime.op.Caster;
import lucee.runtime.op.Decision;
import lucee.runtime.op.Operator;
import lucee.runtime.orm.ORMConfiguration;
import lucee.runtime.orm.ORMEngine;
import lucee.runtime.orm.ORMSession;
import lucee.runtime.regex.Perl5Util;
import lucee.runtime.rest.RestRequestListener;
import lucee.runtime.rest.RestUtil;
import lucee.runtime.security.Credential;
import lucee.runtime.security.CredentialImpl;
import lucee.runtime.security.ScriptProtect;
import lucee.runtime.tag.Login;
import lucee.runtime.tag.TagHandlerPool;
import lucee.runtime.tag.TagUtil;
import lucee.runtime.thread.ThreadsImpl;
import lucee.runtime.type.Array;
import lucee.runtime.type.Collection;
import lucee.runtime.type.Collection.Key;
import lucee.runtime.type.Iterator;
import lucee.runtime.type.KeyImpl;
import lucee.runtime.type.Query;
import lucee.runtime.type.SVArray;
import lucee.runtime.type.Struct;
import lucee.runtime.type.StructImpl;
import lucee.runtime.type.UDF;
import lucee.runtime.type.UDFPlus;
import lucee.runtime.type.dt.TimeSpan;
import lucee.runtime.type.it.ItAsEnum;
import lucee.runtime.type.ref.Reference;
import lucee.runtime.type.ref.VariableReference;
import lucee.runtime.type.scope.Application;
import lucee.runtime.type.scope.Argument;
import lucee.runtime.type.scope.ArgumentImpl;
import lucee.runtime.type.scope.CGI;
import lucee.runtime.type.scope.CGIImpl;
import lucee.runtime.type.scope.CGIImplReadOnly;
import lucee.runtime.type.scope.Client;
import lucee.runtime.type.scope.ClosureScope;
import lucee.runtime.type.scope.Cluster;
import lucee.runtime.type.scope.Cookie;
import lucee.runtime.type.scope.CookieImpl;
import lucee.runtime.type.scope.Form;
import lucee.runtime.type.scope.FormImpl;
import lucee.runtime.type.scope.Local;
import lucee.runtime.type.scope.LocalNotSupportedScope;
import lucee.runtime.type.scope.Request;
import lucee.runtime.type.scope.RequestImpl;
import lucee.runtime.type.scope.Scope;
import lucee.runtime.type.scope.ScopeContext;
import lucee.runtime.type.scope.ScopeFactory;
import lucee.runtime.type.scope.ScopeSupport;
import lucee.runtime.type.scope.Server;
import lucee.runtime.type.scope.Session;
import lucee.runtime.type.scope.Threads;
import lucee.runtime.type.scope.URL;
import lucee.runtime.type.scope.URLForm;
import lucee.runtime.type.scope.URLImpl;
import lucee.runtime.type.scope.Undefined;
import lucee.runtime.type.scope.UndefinedImpl;
import lucee.runtime.type.scope.UrlFormImpl;
import lucee.runtime.type.scope.Variables;
import lucee.runtime.type.scope.VariablesImpl;
import lucee.runtime.type.util.ArrayUtil;
import lucee.runtime.type.util.CollectionUtil;
import lucee.runtime.type.util.KeyConstants;
import lucee.runtime.util.PageContextUtil;
import lucee.runtime.util.VariableUtil;
import lucee.runtime.util.VariableUtilImpl;
import lucee.runtime.writer.BodyContentUtil;
import lucee.runtime.writer.CFMLWriter;
import lucee.runtime.writer.DevNullBodyContent;
/**
* page context for every page object.
* the PageContext is a jsp page context expanded by CFML functionality.
* for example you have the method getSession to get jsp combatible session object (HTTPSession)
* and with sessionScope() you get CFML combatible session object (Struct,Scope).
*/
public final class PageContextImpl extends PageContext {
private static final RefBoolean DUMMY_BOOL = new RefBooleanImpl(false);
private static int counter=0;
/**
* Field <code>pathList</code>
*/
private LinkedList<UDF> udfs=new LinkedList<UDF>();
private LinkedList<PageSource> pathList=new LinkedList<PageSource>();
private LinkedList<PageSource> includePathList=new LinkedList<PageSource>();
private Set<PageSource> includeOnce=new HashSet<PageSource>();
/**
* Field <code>executionTime</code>
*/
protected long executionTime=0;
private HTTPServletRequestWrap req;
private HttpServletResponse rsp;
private HttpServlet servlet;
private JspWriter writer;
private JspWriter forceWriter;
private BodyContentStack bodyContentStack;
private DevNullBodyContent devNull;
private ConfigWebImpl config;
//private DataSourceManager manager;
//private CFMLCompilerImpl compiler;
// Scopes
private ScopeContext scopeContext;
private Variables variablesRoot=new VariablesImpl();//ScopeSupport(false,"variables",Scope.SCOPE_VARIABLES);
private Variables variables=variablesRoot;//new ScopeSupport("variables",Scope.SCOPE_VARIABLES);
private Undefined undefined;
private URLImpl _url=new URLImpl();
private FormImpl _form=new FormImpl();
private URLForm urlForm=new UrlFormImpl(_form,_url);
private URL url;
private Form form;
private RequestImpl request=new RequestImpl();
private CGIImplReadOnly cgiR=new CGIImplReadOnly();
private CGIImpl cgiRW=new CGIImpl();
private Argument argument=new ArgumentImpl();
private static LocalNotSupportedScope localUnsupportedScope=LocalNotSupportedScope.getInstance();
private Local local=localUnsupportedScope;
private Session session;
private Server server;
private Cluster cluster;
private CookieImpl cookie=new CookieImpl();
private Client client;
private Application application;
private DebuggerImpl debugger=new DebuggerImpl();
private long requestTimeout=-1;
private short enablecfoutputonly=0;
private int outputState;
private String cfid;
private String cftoken;
private int id;
private int requestId;
private boolean psq;
private Locale locale;
private TimeZone timeZone;
// Pools
private ErrorPagePool errorPagePool=new ErrorPagePool();
private TagHandlerPool tagHandlerPool;
private FTPPoolImpl ftpPool=new FTPPoolImpl();
private Component activeComponent;
private UDF activeUDF;
private Collection.Key activeUDFCalledName;
//private ComponentScope componentScope=new ComponentScope(this);
private Credential remoteUser;
protected VariableUtilImpl variableUtil=new VariableUtilImpl();
private PageException exception;
private PageSource base;
ApplicationContext applicationContext;
ApplicationContext defaultApplicationContext;
private ScopeFactory scopeFactory=new ScopeFactory();
private Tag parentTag=null;
private Tag currentTag=null;
private Thread thread;
private long startTime;
private DatasourceManagerImpl manager;
private Struct threads;
private boolean hasFamily=false;
private PageContextImpl parent=null;
private List<PageContext> children=null;
private List<Statement> lazyStats;
private boolean fdEnabled;
private ExecutionLog execLog;
private boolean useSpecialMappings;
private ORMSession ormSession;
private boolean isChild;
private boolean gatewayContext;
private Password serverPassword;
private PageException pe;
//private Throwable requestTimeoutException;
private int currentTemplateDialect=CFMLEngine.DIALECT_LUCEE;
private int requestDialect=CFMLEngine.DIALECT_LUCEE;
private boolean ignoreScopes=false;
private int appListenerType=ApplicationListener.TYPE_NONE;
private ThreadsImpl currentThread;
private StackTraceElement[] timeoutStacktrace;
/**
* default Constructor
* @param scopeContext
* @param config Configuration of the CFML Container
* @param queryCache Query Cache Object
* @param id identity of the pageContext
* @param servlet
*/
public PageContextImpl(ScopeContext scopeContext, ConfigWebImpl config, int id,HttpServlet servlet, boolean jsr223) {
// must be first because is used after
tagHandlerPool=config.getTagHandlerPool();
this.servlet=servlet;
this.id=id;
//this.factory=factory;
bodyContentStack=new BodyContentStack();
devNull=bodyContentStack.getDevNullBodyContent();
this.config=config;
manager=new DatasourceManagerImpl(config);
this.scopeContext=scopeContext;
undefined=
new UndefinedImpl(this,getScopeCascadingType());
//this.compiler=compiler;
//tagHandlerPool=config.getTagHandlerPool();
server=ScopeContext.getServerScope(this,jsr223);
defaultApplicationContext=new ClassicApplicationContext(config,"",true,null);
}
public boolean isInitialized() {
return rsp!=null;
}
/**
* return if the PageContext is from a stopped thread, if so it should no longer be used!
* @return
*/
public Throwable getRequestTimeoutException() {
throw new RuntimeException("method no longer supported");
//return requestTimeoutException;
}
/*public void setRequestTimeoutException(Throwable requestTimeoutException) {
this.requestTimeoutException=requestTimeoutException;
}*/
public StackTraceElement[] getTimeoutStackTrace() {
return timeoutStacktrace;
}
public void setTimeoutStackTrace() {
this.timeoutStacktrace=thread.getStackTrace();
}
@Override
public void initialize(
Servlet servlet,
ServletRequest req,
ServletResponse rsp,
String errorPageURL,
boolean needsSession,
int bufferSize,
boolean autoFlush) throws IOException, IllegalStateException, IllegalArgumentException {
initialize(
(HttpServlet)servlet,
(HttpServletRequest)req,
(HttpServletResponse)rsp,
errorPageURL,
needsSession,
bufferSize,
autoFlush,false,false);
}
/**
* initialize a existing page context
* @param servlet
* @param req
* @param rsp
* @param errorPageURL
* @param needsSession
* @param bufferSize
* @param autoFlush
*/
public PageContextImpl initialize(
HttpServlet servlet,
HttpServletRequest req,
HttpServletResponse rsp,
String errorPageURL,
boolean needsSession,
int bufferSize,
boolean autoFlush,
boolean isChild, boolean ignoreScopes) {
appListenerType=ApplicationListener.TYPE_NONE;
this.ignoreScopes=ignoreScopes;
requestId=counter++;
ReqRspUtil.setContentType(rsp,"text/html; charset="+config.getWebCharset().name());
this.isChild=isChild;
applicationContext=defaultApplicationContext;
startTime=System.currentTimeMillis();
thread=Thread.currentThread();
this.req=new HTTPServletRequestWrap(req);
this.rsp=rsp;
this.servlet=servlet;
// Writers
if(config.debugLogOutput()) {
CFMLWriter w = config.getCFMLWriter(this,req,rsp);
w.setAllowCompression(false);
DebugCFMLWriter dcw = new DebugCFMLWriter(w);
bodyContentStack.init(dcw);
debugger.setOutputLog(dcw);
}
else {
bodyContentStack.init(config.getCFMLWriter(this,req,rsp));
}
writer=bodyContentStack.getWriter();
forceWriter=writer;
// Scopes
server=ScopeContext.getServerScope(this,ignoreScopes);
if(hasFamily) {
variablesRoot=new VariablesImpl();
variables=variablesRoot;
request=new RequestImpl();
_url=new URLImpl();
_form=new FormImpl();
urlForm=new UrlFormImpl(_form,_url);
undefined=
new UndefinedImpl(this,getScopeCascadingType());
hasFamily=false;
}
else if(variables==null) {
variablesRoot=new VariablesImpl();
variables=variablesRoot;
}
request.initialize(this);
if(config.mergeFormAndURL()) {
url=urlForm;
form=urlForm;
}
else {
url=_url;
form=_form;
}
//url.initialize(this);
//form.initialize(this);
//undefined.initialize(this);
psq=config.getPSQL();
fdEnabled=!config.allowRequestTimeout();
if(config.getExecutionLogEnabled())
this.execLog=config.getExecutionLogFactory().getInstance(this);
if(debugger!=null)
debugger.init(config);
undefined.initialize(this);
timeoutStacktrace=null;
return this;
}
@Override
public void release() {
config.releaseCacheHandlers(this);
if(config.getExecutionLogEnabled()){
execLog.release();
execLog=null;
}
if(config.debug()) {
if(!gatewayContext && !isChild)
config.getDebuggerPool().store(this, debugger);
debugger.reset();
}
else debugger.resetTraces(); // traces can alo be used when debugging is off
this.serverPassword=null;
// boolean isChild=parent!=null; // isChild is defined in the class outside this method
parent=null;
// Attention have to be before close
if(client!=null){
client.touchAfterRequest(this);
client=null;
}
if(session!=null){
session.touchAfterRequest(this);
session=null;
}
// ORM
if(ormSession!=null){
// flush orm session
try {
ORMEngine engine=ormSession.getEngine();
ORMConfiguration config=engine.getConfiguration(this);
if(config==null || (config.flushAtRequestEnd() && config.autoManageSession())){
ormSession.flushAll(this);
}
ormSession.closeAll(this);
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
ormSession=null;
}
// Scopes
if(hasFamily) {
if(!isChild){
req.disconnect(this);
}
close();
thread=null;
base=null;
if(children!=null) children.clear();
request=null;
_url=null;
_form=null;
urlForm=null;
undefined=null;
variables=null;
variablesRoot=null;
//if(threads!=null && threads.size()>0) threads.clear();
threads=null;
currentThread=null;
}
else {
close();
thread=null;
base=null;
if(variables.isBind()) {
variables=null;
variablesRoot=null;
}
else {
variables=variablesRoot;
variables.release(this);
}
undefined.release(this);
urlForm.release(this);
request.release(this);
}
cgiR.release(this);
cgiRW.release(this);
argument.release(this);
local=localUnsupportedScope;
cookie.release(this);
//if(cluster!=null)cluster.release();
//client=null;
//session=null;
application=null;// not needed at the moment -> application.releaseAfterRequest();
applicationContext=null;
// Properties
requestTimeout=-1;
outputState=0;
cfid=null;
cftoken=null;
locale=null;
timeZone=null;
url=null;
form=null;
currentTemplateDialect=CFMLEngine.DIALECT_LUCEE;
requestDialect=CFMLEngine.DIALECT_LUCEE;
// Pools
errorPagePool.clear();
// lazy statements
if(lazyStats!=null && !lazyStats.isEmpty()){
java.util.Iterator<Statement> it = lazyStats.iterator();
while(it.hasNext()) {
DBUtil.closeEL(it.next());
}
lazyStats.clear();
lazyStats=null;
}
pathList.clear();
includePathList.clear();
executionTime=0;
bodyContentStack.release();
//activeComponent=null;
remoteUser=null;
exception=null;
ftpPool.clear();
parentTag=null;
currentTag=null;
// Req/Rsp
//if(req!=null)
req.clear();
req=null;
rsp=null;
servlet=null;
// Writer
writer=null;
forceWriter=null;
if(pagesUsed.size()>0)pagesUsed.clear();
activeComponent=null;
activeUDF=null;
gatewayContext=false;
manager.release();
includeOnce.clear();
pe=null;
this.literalTimestampWithTSOffset=false;
}
@Override
public void write(String str) throws IOException {
writer.write(str);
}
@Override
public void forceWrite(String str) throws IOException {
forceWriter.write(str);
}
@Override
public void writePSQ(Object o) throws IOException, PageException {
if(o instanceof Date || Decision.isDate(o, false)) {
writer.write(Caster.toString(o));
}
else {
writer.write(psq?Caster.toString(o):StringUtil.replace(Caster.toString(o),"'","''",false));
}
}
// FUTURE add both method to interface
public void writeEncodeFor(String value, String encodeType) throws IOException, PageException { // FUTURE keyword:encodefore add to interface
write(ESAPIEncode.call(this, encodeType, value,false));
}
public void writeEncodeFor(String value, short encodeType) throws IOException, PageException { // FUTURE keyword:encodefore add to interface
write(ESAPIEncode.encode(value, encodeType, false));
}
@Override
public void flush() {
try {
getOut().flush();
} catch (IOException e) {}
}
@Override
public void close() {
IOUtil.closeEL(getOut());
}
public PageSource getRelativePageSource(String realPath) {
SystemOut.print(config.getOutWriter(),"method getRelativePageSource is deprecated");
if(StringUtil.startsWith(realPath,'/')) return PageSourceImpl.best(getPageSources(realPath));
if(pathList.size()==0) return null;
return pathList.getLast().getRealPage(realPath);
}
public PageSource getRelativePageSourceExisting(String realPath) {
if(StringUtil.startsWith(realPath,'/')) return getPageSourceExisting(realPath);
if(pathList.size()==0) return null;
PageSource ps = pathList.getLast().getRealPage(realPath);
if(PageSourceImpl.pageExist(ps)) return ps;
return null;
}
/**
*
* @param realPath
* @param previous relative not to the caller, relative to the callers caller
* @return
*/
public PageSource getRelativePageSourceExisting(String realPath, boolean previous ) {
if(StringUtil.startsWith(realPath,'/')) return getPageSourceExisting(realPath);
if(pathList.size()==0) return null;
PageSource ps=null,tmp=null;
if(previous) {
boolean valid=false;
ps=pathList.getLast();
for(int i=pathList.size()-2;i>=0;i--){
tmp=pathList.get(i);
if(tmp!=ps) {
ps=tmp;
valid=true;
break;
}
}
if(!valid) return null;
}
else ps=pathList.getLast();
ps = ps.getRealPage(realPath);
if(PageSourceImpl.pageExist(ps)) return ps;
return null;
}
public PageSource[] getRelativePageSources(String realPath) {
if(StringUtil.startsWith(realPath,'/')) return getPageSources(realPath);
if(pathList.size()==0) return null;
return new PageSource[]{ pathList.getLast().getRealPage(realPath)};
}
public PageSource getPageSource(String realPath) {
return PageSourceImpl.best(config.getPageSources(this,applicationContext.getMappings(),realPath,false,useSpecialMappings,true));
}
public PageSource[] getPageSources(String realPath) { // to not change, this is used in the flex extension
return config.getPageSources(this,applicationContext.getMappings(),realPath,false,useSpecialMappings,true);
}
public PageSource getPageSourceExisting(String realPath) { // do not change, this method is used in flex extension
return config.getPageSourceExisting(this,applicationContext.getMappings(),realPath,false,useSpecialMappings,true,false);
}
public boolean useSpecialMappings(boolean useTagMappings) {
boolean b=this.useSpecialMappings;
this.useSpecialMappings=useTagMappings;
return b;
}
public boolean useSpecialMappings() {
return useSpecialMappings;
}
public Resource getPhysical(String realPath, boolean alsoDefaultMapping){
return config.getPhysical(applicationContext.getMappings(),realPath, alsoDefaultMapping);
}
@Override
public PageSource toPageSource(Resource res, PageSource defaultValue){
return config.toPageSource(applicationContext.getMappings(),res, defaultValue);
}
@Override
public void doInclude(String realPath) throws PageException {
_doInclude(getRelativePageSources(realPath),false,getCachedWithin(ConfigWeb.CACHEDWITHIN_INCLUDE));
}
@Override
public void doInclude(String realPath, boolean runOnce) throws PageException {
_doInclude(getRelativePageSources(realPath),runOnce,getCachedWithin(ConfigWeb.CACHEDWITHIN_INCLUDE));
}
// used by the transformer
public void doInclude(String realPath, boolean runOnce, Object cachedWithin) throws PageException {
if(cachedWithin==null) cachedWithin=getCachedWithin(ConfigWeb.CACHEDWITHIN_INCLUDE);
_doInclude(getRelativePageSources(realPath),runOnce,cachedWithin);
}
@Override
public void doInclude(PageSource[] sources, boolean runOnce) throws PageException {
_doInclude(sources, runOnce,getCachedWithin(ConfigWeb.CACHEDWITHIN_INCLUDE));
}
// IMPORTANT!!! we do not getCachedWithin in this method, because Modern|ClassicAppListener is calling this method and in this case it should not be used
public void _doInclude(PageSource[] sources, boolean runOnce, Object cachedWithin) throws PageException {
if(cachedWithin==null) {
_doInclude(sources, runOnce);
return;
}
// ignore call when runonce an it is not first call
if(runOnce) {
Page currentPage = PageSourceImpl.loadPage(this, sources);
if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
}
// get cached data
String id=CacheHandlerCollectionImpl.createId(sources);
CacheHandler ch = config.getCacheHandlerCollection(Config.CACHE_TYPE_INCLUDE,null).getInstanceMatchingObject(cachedWithin,null);
CacheItem ci=ch!=null?ch.get(this, id):null;
if(ci instanceof IncludeCacheItem) {
try {
write(((IncludeCacheItem)ci).getOutput());
return;
} catch (IOException e) {
throw Caster.toPageException(e);
}
}
long start = System.nanoTime();
BodyContent bc = pushBody();
try {
_doInclude(sources, runOnce);
String out = bc.getString();
if(ch!=null)ch.set(this, id,cachedWithin,new IncludeCacheItem(
out
,ArrayUtil.isEmpty(sources)?null:sources[0]
,System.nanoTime()-start));
return;
}
finally {
BodyContentUtil.flushAndPop(this,bc);
}
}
private void _doInclude(PageSource[] sources, boolean runOnce) throws PageException {
// debug
if(!gatewayContext && config.debug()) {
long currTime=executionTime;
long exeTime=0;
long time=System.nanoTime();
Page currentPage = PageSourceImpl.loadPage(this, sources);
notSupported(config,currentPage.getPageSource());
if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
DebugEntryTemplate debugEntry=debugger.getEntry(this,currentPage.getPageSource());
try {
addPageSource(currentPage.getPageSource(),true);
debugEntry.updateFileLoadTime((System.nanoTime()-time));
exeTime=System.nanoTime();
currentPage.call(this);
}
catch(Throwable t){
ExceptionUtil.rethrowIfNecessary(t);
PageException pe = Caster.toPageException(t);
if(Abort.isAbort(pe)) {
if(Abort.isAbort(pe,Abort.SCOPE_REQUEST))throw pe;
}
else {
if(fdEnabled){
FDSignal.signal(pe, false);
}
pe.addContext(currentPage.getPageSource(),-187,-187, null);// TODO was soll das 187
throw pe;
}
}
finally {
includeOnce.add(currentPage.getPageSource());
long diff= ((System.nanoTime()-exeTime)-(executionTime-currTime));
executionTime+=(System.nanoTime()-time);
debugEntry.updateExeTime(diff);
removeLastPageSource(true);
}
}
// no debug
else {
Page currentPage = PageSourceImpl.loadPage(this, sources);
notSupported(config,currentPage.getPageSource());
if(runOnce && includeOnce.contains(currentPage.getPageSource())) return;
try {
addPageSource(currentPage.getPageSource(),true);
currentPage.call(this);
}
catch(Throwable t){
ExceptionUtil.rethrowIfNecessary(t);
PageException pe = Caster.toPageException(t);
if(Abort.isAbort(pe)) {
if(Abort.isAbort(pe,Abort.SCOPE_REQUEST))throw pe;
}
else {
pe.addContext(currentPage.getPageSource(),-187,-187, null);
throw pe;
}
}
finally {
includeOnce.add(currentPage.getPageSource());
removeLastPageSource(true);
}
}
}
public static void notSupported(Config config,PageSource ps) throws ApplicationException {
if(ps.getDialect()==CFMLEngine.DIALECT_LUCEE && config instanceof ConfigImpl && !((ConfigImpl)config).allowLuceeDialect())
notSupported();
}
public static void notSupported() throws ApplicationException {
throw new ApplicationException(
"The Lucee dialect is disabled, to enable the dialect set the environment variable or system property \"lucee.enable.dialect\" to \"true\" or set the attribute \"allow-lucee-dialect\" to \"true\" with the \"compiler\" tag inside the lucee-server.xml.");
}
@Override
public Array getTemplatePath() throws PageException {
int len=includePathList.size();
SVArray sva = new SVArray();
PageSource ps;
for(int i=0;i<len;i++) {
ps=includePathList.get(i);
if(i==0) {
if(!ps.equals(getBasePageSource()))
sva.append(getBasePageSource().getResourceTranslated(this).getAbsolutePath());
}
sva.append(ps.getResourceTranslated(this).getAbsolutePath());
}
//sva.setPosition(sva.size());
return sva;
}
public List<PageSource> getPageSourceList() {
return (List<PageSource>) pathList.clone();
}
public PageSource getPageSource(int index) {
return includePathList.get(index-1);
}
public synchronized void copyStateTo(PageContextImpl other) {
// cfid (we do this that way, otherwise we only have the same cfid if the current pc has defined cfid in cookie or url)
getCFID();
other.cfid=cfid;
other.cftoken=cftoken;
// private Debugger debugger=new DebuggerImpl();
other.requestTimeout=requestTimeout;
other.locale=locale;
other.timeZone=timeZone;
other.fdEnabled=fdEnabled;
other.useSpecialMappings=useSpecialMappings;
other.serverPassword=serverPassword;
hasFamily=true;
other.hasFamily=true;
other.parent=this;
if(children==null) children=new ArrayList<PageContext>();
children.add(other);
other.applicationContext=applicationContext;
other.thread=Thread.currentThread();
other.startTime=System.currentTimeMillis();
// path
other.base=base;
java.util.Iterator<PageSource> it = includePathList.iterator();
while(it.hasNext()) {
other.includePathList.add(it.next());
}
it = pathList.iterator();
while(it.hasNext()) {
other.pathList.add(it.next());
}
// scopes
other.req=req;
other.request=request;
other.form=form;
other.url=url;
other.urlForm=urlForm;
other._url=_url;
other._form=_form;
other.variables=variables;
other.undefined=new UndefinedImpl(other,(short)other.undefined.getType());
// writers
other.bodyContentStack.init(config.getCFMLWriter(this,other.req,other.rsp));
//other.bodyContentStack.init(other.req,other.rsp,other.config.isSuppressWhitespace(),other.config.closeConnection(), other.config.isShowVersion(),config.contentLength(),config.allowCompression());
other.writer=other.bodyContentStack.getWriter();
other.forceWriter=other.writer;
other.psq=psq;
other.gatewayContext=gatewayContext;
// thread
/*if(threads!=null){
synchronized (threads) {
java.util.Iterator<Entry<Key, Object>> it2 = threads.entryIterator();
Entry<Key, Object> entry;
while(it2.hasNext()) {
entry = it2.next();
other.setThreadScope(entry.getKey(), (Threads)entry.getValue());
}
}
}*/
// initialize stuff
other.undefined.initialize(other);
}
public int getCurrentLevel() {
return includePathList.size()+1;
}
@Override
public PageSource getCurrentPageSource() {
if(pathList.isEmpty()) return null;
return pathList.getLast();
}
@Override
public PageSource getCurrentPageSource(PageSource defaultvalue) {
if(pathList.isEmpty()) return defaultvalue;
return pathList.getLast();
}
/**
* @return the current template PageSource
*/
public PageSource getCurrentTemplatePageSource() {
if(includePathList.isEmpty()) return null;
return includePathList.getLast();
}
/**
* @return base template file
*/
public PageSource getBasePageSource() {
return base;
}
@Override
public Resource getRootTemplateDirectory() {
return config.getResource(ReqRspUtil.getRootPath(servlet.getServletContext()));
}
@Override
public Scope scope(int type) throws PageException {
switch(type) {
case Scope.SCOPE_UNDEFINED: return undefinedScope();
case Scope.SCOPE_URL: return urlScope();
case Scope.SCOPE_FORM: return formScope();
case Scope.SCOPE_VARIABLES: return variablesScope();
case Scope.SCOPE_REQUEST: return requestScope();
case Scope.SCOPE_CGI: return cgiScope();
case Scope.SCOPE_APPLICATION: return applicationScope();
case Scope.SCOPE_ARGUMENTS: return argumentsScope();
case Scope.SCOPE_SESSION: return sessionScope();
case Scope.SCOPE_SERVER: return serverScope();
case Scope.SCOPE_COOKIE: return cookieScope();
case Scope.SCOPE_CLIENT: return clientScope();
case Scope.SCOPE_LOCAL:
case ScopeSupport.SCOPE_VAR: return localScope();
case Scope.SCOPE_CLUSTER:return clusterScope();
}
return variables;
}
public Scope scope(String strScope,Scope defaultValue) throws PageException {
if(strScope==null)return defaultValue;
if(ignoreScopes()) {
if("arguments".equals(strScope)) return argumentsScope();
if("local".equals(strScope)) return localScope();
if("request".equals(strScope)) return requestScope();
if("variables".equals(strScope)) return variablesScope();
if("server".equals(strScope)) return serverScope();
return defaultValue;
}
strScope=strScope.toLowerCase().trim();
if("variables".equals(strScope)) return variablesScope();
if("url".equals(strScope)) return urlScope();
if("form".equals(strScope)) return formScope();
if("request".equals(strScope)) return requestScope();
if("cgi".equals(strScope)) return cgiScope();
if("application".equals(strScope)) return applicationScope();
if("arguments".equals(strScope)) return argumentsScope();
if("session".equals(strScope)) return sessionScope();
if("server".equals(strScope)) return serverScope();
if("cookie".equals(strScope)) return cookieScope();
if("client".equals(strScope)) return clientScope();
if("local".equals(strScope)) return localScope();
if("cluster".equals(strScope)) return clusterScope();
return defaultValue;
}
@Override
public Undefined undefinedScope() {
if(!undefined.isInitalized()) undefined.initialize(this);
return undefined;
}
/**
* @return undefined scope, undefined scope is a placeholder for the scopecascading
*/
public Undefined us() {
if(!undefined.isInitalized()) undefined.initialize(this);
return undefined;
}
public Scope usl() {
if(!undefined.isInitalized()) undefined.initialize(this);
if(undefined.getCheckArguments()) return undefined.localScope();
return undefined;
}
@Override
public Variables variablesScope() { return variables; }
@Override
public URL urlScope() {
if(!url.isInitalized())url.initialize(this);
return url;
}
@Override
public Form formScope() {
if(!form.isInitalized())form.initialize(this);
return form;
}
@Override
public URLForm urlFormScope() {
if(!urlForm.isInitalized())urlForm.initialize(this);
return urlForm;
}
@Override
public Request requestScope() { return request; }
@Override
public CGI cgiScope() {
CGI cgi=applicationContext.getCGIScopeReadonly()?cgiR:cgiRW;
if(!cgi.isInitalized())cgi.initialize(this);
return cgi;
}
@Override
public Application applicationScope() throws PageException {
if(application==null) {
if(!applicationContext.hasName())
throw new ExpressionException("there is no application context defined for this application",hintAplication("you can define a application context"));
application=scopeContext.getApplicationScope(this,DUMMY_BOOL);
}
return application;
}
private String hintAplication(String prefix) {
boolean isCFML=getRequestDialect()==CFMLEngine.DIALECT_CFML;
return prefix+" with the tag "
+(isCFML?lucee.runtime.config.Constants.CFML_APPLICATION_TAG_NAME:lucee.runtime.config.Constants.LUCEE_APPLICATION_TAG_NAME)
+"or with the "
+(isCFML?lucee.runtime.config.Constants.CFML_APPLICATION_EVENT_HANDLER:lucee.runtime.config.Constants.LUCEE_APPLICATION_EVENT_HANDLER);
}
@Override
public Argument argumentsScope() { return argument; }
@Override
public Argument argumentsScope(boolean bind) {
//Argument a=argumentsScope();
if(bind)argument.setBind(true);
return argument;
}
@Override
public Local localScope() {
//if(local==localUnsupportedScope)
// throw new PageRuntimeException(new ExpressionException("Unsupported Context for Local Scope"));
return local;
}
@Override
public Local localScope(boolean bind) {
if(bind)local.setBind(true);
//if(local==localUnsupportedScope)
// throw new PageRuntimeException(new ExpressionException("Unsupported Context for Local Scope"));
return local;
}
public Object localGet() throws PageException {
return localGet(false);
}
public Object localGet(boolean bind, Object defaultValue) {
if(undefined.getCheckArguments()){
return localScope(bind);
}
return undefinedScope().get(KeyConstants._local,defaultValue);
}
public Object localGet(boolean bind) throws PageException {
// inside a local supported block
if(undefined.getCheckArguments()){
return localScope(bind);
}
return undefinedScope().get(KeyConstants._local);
}
public Object localTouch() throws PageException {
return localTouch(false);
}
public Object localTouch(boolean bind) throws PageException {
// inside a local supported block
if(undefined.getCheckArguments()){
return localScope(bind);
}
return touch(undefinedScope(), KeyConstants._local);
//return undefinedScope().get(LOCAL);
}
public Object thisGet() throws PageException { return thisTouch();}
public Object thisTouch() throws PageException {
// inside a component
if(undefined.variablesScope() instanceof ComponentScope){
return ((ComponentScope)undefined.variablesScope()).getComponent();
}
return undefinedScope().get(KeyConstants._THIS);
}
public Object thisGet(Object defaultValue) { return thisTouch(defaultValue);}
public Object thisTouch(Object defaultValue) {
// inside a component
if(undefined.variablesScope() instanceof ComponentScope){
return ((ComponentScope)undefined.variablesScope()).getComponent();
}
return undefinedScope().get(KeyConstants._THIS,defaultValue);
}
public Object staticGet() throws PageException { return staticTouch();}
public Object staticTouch() throws PageException {
// inside a component
if(undefined.variablesScope() instanceof ComponentScope){
return getStatic(undefined);
}
return undefinedScope().get(KeyConstants._STATIC);
}
public Object staticGet(Object defaultValue) { return staticTouch(defaultValue);}
public Object staticTouch(Object defaultValue) {
// inside a component
if(undefined.variablesScope() instanceof ComponentScope){
return getStatic(undefined);
}
return undefinedScope().get(KeyConstants._STATIC,defaultValue);
}
private Scope getStatic(Undefined undefined) {
return ((ComponentScope)undefined.variablesScope()).getComponent().staticScope();
}
/**
* @param local sets the current local scope
* @param argument sets the current argument scope
*/
public void setFunctionScopes(Local local,Argument argument) {
this.argument=argument;
this.local=local;
undefined.setFunctionScopes(local,argument);
}
@Override
public Session sessionScope() throws PageException {
return sessionScope(true);
}
public Session sessionScope(boolean checkExpires) throws PageException {
if(session==null) {
checkSessionContext();
session=scopeContext.getSessionScope(this,DUMMY_BOOL);
}
return session;
}
public void invalidateUserScopes(boolean migrateSessionData,boolean migrateClientData) throws PageException {
checkSessionContext();
scopeContext.invalidateUserScope(this, migrateSessionData, migrateClientData);
}
private void checkSessionContext() throws ExpressionException {
if(!applicationContext.hasName())
throw new ExpressionException("there is no session context defined for this application",
hintAplication("you can define a session context"));
if(!applicationContext.isSetSessionManagement())
throw new ExpressionException("session scope is not enabled",
hintAplication("you can enable session scope"));
}
@Override
public Server serverScope() {
//if(!server.isInitalized()) server.initialize(this);
return server;
}
public void reset() {
server=ScopeContext.getServerScope(this,ignoreScopes());
}
@Override
public Cluster clusterScope() throws PageException {
return clusterScope(true);
}
public Cluster clusterScope(boolean create) throws PageException {
if(cluster==null && create) {
cluster=ScopeContext.getClusterScope(config,create);
//cluster.initialize(this);
}
//else if(!cluster.isInitalized()) cluster.initialize(this);
return cluster;
}
@Override
public Cookie cookieScope() {
if(!cookie.isInitalized()) cookie.initialize(this);
return cookie;
}
@Override
public Client clientScope() throws PageException {
if(client==null) {
if(!applicationContext.hasName())
throw new ExpressionException("there is no client context defined for this application",
hintAplication("you can define a client context"));
if(!applicationContext.isSetClientManagement())
throw new ExpressionException("client scope is not enabled",
hintAplication("you can enable client scope"));
client= scopeContext.getClientScope(this);
}
return client;
}
public Client clientScopeEL() {
if(client==null) {
if(applicationContext==null || !applicationContext.hasName()) return null;
if(!applicationContext.isSetClientManagement()) return null;
client= scopeContext.getClientScopeEL(this);
}
return client;
}
public Object set(Object coll, String key, Object value) {
throw new NoLongerSupported();
//return variableUtil.set(this,coll,key,value);
}
@Override
public Object set(Object coll, Collection.Key key, Object value) throws PageException {
return variableUtil.set(this,coll,key,value);
}
/*public Object touch(Object coll, String key) throws PageException {
Object o=getCollection(coll,key,null);
if(o!=null) return o;
return set(coll,key,new StructImpl());
}*/
@Override
public Object touch(Object coll, Collection.Key key) throws PageException {
Object o=getCollection(coll,key,null);
if(o!=null) return o;
return set(coll,key,new StructImpl());
}
/*private Object _touch(Scope scope, String key) throws PageException {
Object o=scope.get(key,null);
if(o!=null) return o;
return scope.set(key, new StructImpl());
}*/
@Override
public Object getCollection(Object coll, String key) throws PageException {
return variableUtil.getCollection(this,coll,key);
}
@Override
public Object getCollection(Object coll, Collection.Key key) throws PageException {
return variableUtil.getCollection(this,coll,key);
}
@Override
public Object getCollection(Object coll, String key, Object defaultValue) {
return variableUtil.getCollection(this,coll,key,defaultValue);
}
@Override
public Object getCollection(Object coll, Collection.Key key, Object defaultValue) {
return variableUtil.getCollection(this,coll,key,defaultValue);
}
@Override
public Object get(Object coll, String key) throws PageException {
return variableUtil.get(this,coll,key);
}
@Override
public Object get(Object coll, Collection.Key key) throws PageException {
return variableUtil.get(this,coll,key);
}
@Override
public Reference getReference(Object coll, String key) throws PageException {
return new VariableReference(coll,key);
}
public Reference getReference(Object coll, Collection.Key key) throws PageException {
return new VariableReference(coll,key);
}
@Override
public Object get(Object coll, String key, Object defaultValue) {
return variableUtil.get(this,coll,key, defaultValue);
}
@Override
public Object get(Object coll, Collection.Key key, Object defaultValue) {
return variableUtil.get(this,coll,key, defaultValue);
}
@Override
public Object setVariable(String var, Object value) throws PageException {
//return new CFMLExprInterpreter().interpretReference(this,new ParserString(var)).set(value);
return VariableInterpreter.setVariable(this,var,value);
}
@Override
public Object getVariable(String var) throws PageException {
return VariableInterpreter.getVariable(this,var);
}
public void param(String type, String name, Object defaultValue,String regex) throws PageException {
_param(type, name, defaultValue,Double.NaN,Double.NaN,regex,-1);
}
public void param(String type, String name, Object defaultValue,double min, double max) throws PageException {
_param(type, name, defaultValue,min,max,null,-1);
}
public void param(String type, String name, Object defaultValue,int maxLength) throws PageException {
_param(type, name, defaultValue,Double.NaN,Double.NaN,null,maxLength);
}
public void param(String type, String name, Object defaultValue) throws PageException {
_param(type, name, defaultValue,Double.NaN,Double.NaN,null,-1);
}
// used by generated code FUTURE add to interface
public void subparam(String type, String name, final Object value, double min,double max,
String strPattern, int maxLength, final boolean isNew) throws PageException {
// check attributes type
if(type==null)type="any";
else type=type.trim().toLowerCase();
// cast and set value
if(!"any".equals(type)) {
// range
if("range".equals(type)) {
boolean hasMin=Decision.isValid(min);
boolean hasMax=Decision.isValid(max);
double number = Caster.toDoubleValue(value);
if(!hasMin && !hasMax)
throw new ExpressionException("you need to define one of the following attributes [min,max], when type is set to [range]");
if(hasMin && number<min)
throw new ExpressionException("The number ["+Caster.toString(number)+"] is to small, the number must be at least ["+Caster.toString(min)+"]");
if(hasMax && number>max)
throw new ExpressionException("The number ["+Caster.toString(number)+"] is to big, the number cannot be bigger than ["+Caster.toString(max)+"]");
setVariable(name,Caster.toDouble(number));
}
// regex
else if("regex".equals(type) || "regular_expression".equals(type)) {
String str=Caster.toString(value);
if(strPattern==null) throw new ExpressionException("Missing attribute [pattern]");
if(!Perl5Util.matches(strPattern, str))
throw new ExpressionException("The value ["+str+"] doesn't match the provided pattern ["+strPattern+"]");
setVariable(name,str);
}
else if ( type.equals( "int" ) || type.equals( "integer" ) ) {
if ( !Decision.isInteger( value ) )
throw new ExpressionException( "The value [" + value + "] is not a valid integer" );
setVariable( name, value );
}
else {
if(!Decision.isCastableTo(type,value,true,true,maxLength)) {
if(maxLength>-1 && ("email".equalsIgnoreCase(type) || "url".equalsIgnoreCase(type) || "string".equalsIgnoreCase(type))) {
StringBuilder msg=new StringBuilder(CasterException.createMessage(value, type));
msg.append(" with a maximum length of "+maxLength+" characters");
throw new CasterException(msg.toString());
}
throw new CasterException(value,type);
}
setVariable(name,value);
//REALCAST setVariable(name,Caster.castTo(this,type,value,true));
}
}
else if(isNew) setVariable(name,value);
}
private void _param(String type, String name, Object defaultValue, double min,double max, String strPattern, int maxLength) throws PageException {
// check attributes name
if(StringUtil.isEmpty(name))
throw new ExpressionException("The attribute name is required");
Object value=null;
boolean isNew=false;
// get value
value=VariableInterpreter.getVariableEL(this,name,NullSupportHelper.NULL(this));
if(NullSupportHelper.NULL(this)==value) {
if(defaultValue==null)
throw new ExpressionException("The required parameter ["+name+"] was not provided.");
value=defaultValue;
isNew=true;
}
subparam(type, name, value, min, max, strPattern, maxLength, isNew);
}
/*private void paramX(String type, String name, Object defaultValue, double min,double max, String strPattern, int maxLength) throws PageException {
// check attributes type
if(type==null)type="any";
else type=type.trim().toLowerCase();
// check attributes name
if(StringUtil.isEmpty(name))
throw new ExpressionException("The attribute name is required");
Object value=null;
boolean isNew=false;
// get value
value=VariableInterpreter.getVariableEL(this,name,NullSupportHelper.NULL(this));
if(NullSupportHelper.NULL(this)==value) {
if(defaultValue==null)
throw new ExpressionException("The required parameter ["+name+"] was not provided.");
value=defaultValue;
isNew=true;
}
// cast and set value
if(!"any".equals(type)) {
// range
if("range".equals(type)) {
boolean hasMin=Decision.isValid(min);
boolean hasMax=Decision.isValid(max);
double number = Caster.toDoubleValue(value);
if(!hasMin && !hasMax)
throw new ExpressionException("you need to define one of the following attributes [min,max], when type is set to [range]");
if(hasMin && number<min)
throw new ExpressionException("The number ["+Caster.toString(number)+"] is to small, the number must be at least ["+Caster.toString(min)+"]");
if(hasMax && number>max)
throw new ExpressionException("The number ["+Caster.toString(number)+"] is to big, the number cannot be bigger than ["+Caster.toString(max)+"]");
setVariable(name,Caster.toDouble(number));
}
// regex
else if("regex".equals(type) || "regular_expression".equals(type)) {
String str=Caster.toString(value);
if(strPattern==null) throw new ExpressionException("Missing attribute [pattern]");
if(!Perl5Util.matches(strPattern, str))
throw new ExpressionException("The value ["+str+"] doesn't match the provided pattern ["+strPattern+"]");
setVariable(name,str);
}
else if ( type.equals( "int" ) || type.equals( "integer" ) ) {
if ( !Decision.isInteger( value ) )
throw new ExpressionException( "The value [" + value + "] is not a valid integer" );
setVariable( name, value );
}
else {
if(!Decision.isCastableTo(type,value,true,true,maxLength)) {
if(maxLength>-1 && ("email".equalsIgnoreCase(type) || "url".equalsIgnoreCase(type) || "string".equalsIgnoreCase(type))) {
StringBuilder msg=new StringBuilder(CasterException.createMessage(value, type));
msg.append(" with a maximum length of "+maxLength+" characters");
throw new CasterException(msg.toString());
}
throw new CasterException(value,type);
}
setVariable(name,value);
//REALCAST setVariable(name,Caster.castTo(this,type,value,true));
}
}
else if(isNew) setVariable(name,value);
}*/
@Override
public Object removeVariable(String var) throws PageException {
return VariableInterpreter.removeVariable(this,var);
}
/**
* a variable reference, references to variable, to modifed it, with global effect.
* @param var variable name to get
* @return return a variable reference by string syntax ("scopename.key.key" -> "url.name")
* @throws PageException
*/
public VariableReference getVariableReference(String var) throws PageException {
return VariableInterpreter.getVariableReference(this,var);
}
@Override
public Object getFunction(Object coll, String key, Object[] args) throws PageException {
return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args);
}
@Override
public Object getFunction(Object coll, Key key, Object[] args) throws PageException {
return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args);
}
// FUTURE add to interface
public Object getFunction(Object coll, Key key, Object[] args, Object defaultValue) {
return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args,false,defaultValue);
}
public Object getFunction2(Object coll, Key key, Object[] args, Object defaultValue) {
return variableUtil.callFunctionWithoutNamedValues(this,coll,key,args,true,defaultValue);
}
@Override
public Object getFunctionWithNamedValues(Object coll, String key, Object[] args) throws PageException {
return variableUtil.callFunctionWithNamedValues(this,coll,key,args);
}
@Override
public Object getFunctionWithNamedValues(Object coll, Key key, Object[] args) throws PageException {
return variableUtil.callFunctionWithNamedValues(this,coll,key,args);
}
// FUTURE add to interface
public Object getFunctionWithNamedValues(Object coll, Key key, Object[] args, Object defaultValue) {
return variableUtil.callFunctionWithNamedValues(this,coll,key,args,false,defaultValue);
}
public Object getFunctionWithNamedValues2(Object coll, Key key, Object[] args, Object defaultValue) {
return variableUtil.callFunctionWithNamedValues(this,coll,key,args,true,defaultValue);
}
@Override
public ConfigWeb getConfig() {
return config;
}
@Override
public Iterator getIterator(String key) throws PageException {
Object o=VariableInterpreter.getVariable(this,key);
if(o instanceof Iterator) return (Iterator) o;
throw new ExpressionException("["+key+"] is not a iterator object");
}
@Override
public Query getQuery(String key) throws PageException {
Object value=VariableInterpreter.getVariable(this,key);
if(Decision.isQuery(value)) return Caster.toQuery(value);
throw new CasterException(value,Query.class);///("["+key+"] is not a query object, object is from type ");
}
@Override
public Query getQuery(Object value) throws PageException {
if(Decision.isQuery(value)) return Caster.toQuery(value);
value=VariableInterpreter.getVariable(this,Caster.toString(value));
if(Decision.isQuery(value)) return Caster.toQuery(value);
throw new CasterException(value,Query.class);
}
@Override
public void setAttribute(String name, Object value) {
try {
if(value==null)removeVariable(name);
else setVariable(name,value);
} catch (PageException e) {}
}
@Override
public void setAttribute(String name, Object value, int scope) {
switch(scope){
case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
if(value==null) getServletContext().removeAttribute(name);
else getServletContext().setAttribute(name, value);
break;
case javax.servlet.jsp.PageContext.PAGE_SCOPE:
setAttribute(name, value);
break;
case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
if(value==null) req.removeAttribute(name);
else setAttribute(name, value);
break;
case javax.servlet.jsp.PageContext.SESSION_SCOPE:
HttpSession s = req.getSession(true);
if(value==null)s.removeAttribute(name);
else s.setAttribute(name, value);
break;
}
}
@Override
public Object getAttribute(String name) {
try {
return getVariable(name);
} catch (PageException e) {
return null;
}
}
@Override
public Object getAttribute(String name, int scope) {
switch(scope){
case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
return getServletContext().getAttribute(name);
case javax.servlet.jsp.PageContext.PAGE_SCOPE:
return getAttribute(name);
case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
return req.getAttribute(name);
case javax.servlet.jsp.PageContext.SESSION_SCOPE:
HttpSession s = req.getSession();
if(s!=null)return s.getAttribute(name);
break;
}
return null;
}
@Override
public Object findAttribute(String name) {
// page
Object value=getAttribute(name);
if(value!=null) return value;
// request
value=req.getAttribute(name);
if(value!=null) return value;
// session
HttpSession s = req.getSession();
value=s!=null?s.getAttribute(name):null;
if(value!=null) return value;
// application
value=getServletContext().getAttribute(name);
if(value!=null) return value;
return null;
}
@Override
public void removeAttribute(String name) {
setAttribute(name, null);
}
@Override
public void removeAttribute(String name, int scope) {
setAttribute(name, null,scope);
}
@Override
public int getAttributesScope(String name) {
// page
if(getAttribute(name)!=null) return PageContext.PAGE_SCOPE;
// request
if(req.getAttribute(name) != null) return PageContext.REQUEST_SCOPE;
// session
HttpSession s = req.getSession();
if(s!=null && s.getAttribute(name) != null) return PageContext.SESSION_SCOPE;
// application
if(getServletContext().getAttribute(name)!=null) return PageContext.APPLICATION_SCOPE;
return 0;
}
@Override
public Enumeration<String> getAttributeNamesInScope(int scope) {
switch(scope){
case javax.servlet.jsp.PageContext.APPLICATION_SCOPE:
return getServletContext().getAttributeNames();
case javax.servlet.jsp.PageContext.PAGE_SCOPE:
return ItAsEnum.toStringEnumeration(variablesScope().keyIterator());
case javax.servlet.jsp.PageContext.REQUEST_SCOPE:
return req.getAttributeNames();
case javax.servlet.jsp.PageContext.SESSION_SCOPE:
return req.getSession(true).getAttributeNames();
}
return null;
}
@Override
public JspWriter getOut() {
return forceWriter;
}
@Override
public HttpSession getSession() {
return getHttpServletRequest().getSession();
}
@Override
public Object getPage() {
return variablesScope();
}
@Override
public ServletRequest getRequest() {
return getHttpServletRequest();
}
@Override
public HttpServletRequest getHttpServletRequest() {
return req;
}
@Override
public ServletResponse getResponse() {
return rsp;
}
@Override
public HttpServletResponse getHttpServletResponse() {
return rsp;
}
public OutputStream getResponseStream() throws IOException {
return getRootOut().getResponseStream();
}
@Override
public Exception getException() {
// TODO impl
return exception;
}
@Override
public ServletConfig getServletConfig() {
return config;
}
@Override
public ServletContext getServletContext() {
return servlet.getServletContext();
}
private static String repl(String haystack, String needle, String replacement) {
StringBuilder regex=new StringBuilder("#[\\s]*error[\\s]*\\.[\\s]*");
char[] carr = needle.toCharArray();
for(int i=0;i<carr.length;i++){
regex.append("[");
regex.append(Character.toLowerCase(carr[i]));
regex.append(Character.toUpperCase(carr[i]));
regex.append("]");
}
regex.append("[\\s]*#");
//print.o(regex);
haystack=haystack.replaceAll(regex.toString(), replacement);
//print.o(haystack);
return haystack;
}
@Override
public void handlePageException(PageException pe) {
handlePageException(pe, true);
}
public void handlePageException(PageException pe, boolean setHeader) {
if(!Abort.isSilentAbort(pe)) {
//if(requestTimeoutException!=null)
// pe=Caster.toPageException(requestTimeoutException);
int statusCode=getStatusCode(pe);
// prepare response
if(rsp!=null) {
// content-type
Charset cs = ReqRspUtil.getCharacterEncoding(this,rsp);
if(cs==null) ReqRspUtil.setContentType(rsp,"text/html");
else ReqRspUtil.setContentType(rsp,"text/html; charset=" + cs.name());
// expose error message in header
if(rsp!=null && pe.getExposeMessage())
rsp.setHeader("exception-message", StringUtil.emptyIfNull(pe.getMessage()).replace('\n', ' '));
// status code
if(getConfig().getErrorStatusCode())rsp.setStatus(statusCode);
}
ErrorPage ep=errorPagePool.getErrorPage(pe,ErrorPageImpl.TYPE_EXCEPTION);
//ExceptionHandler.printStackTrace(this,pe);
ExceptionHandler.log(getConfig(),pe);
// error page exception
if(ep!=null) {
try {
Struct sct=pe.getErrorBlock(this,ep);
variablesScope().setEL(KeyConstants._error,sct);
variablesScope().setEL(KeyConstants._cferror,sct);
doInclude(new PageSource[]{ep.getTemplate()},false);
return;
} catch(Throwable t) {
ExceptionUtil.rethrowIfNecessary(t);
if(Abort.isSilentAbort(t)) return;
pe=Caster.toPageException(t);
}
}
// error page request
ep=errorPagePool.getErrorPage(pe,ErrorPageImpl.TYPE_REQUEST);
if(ep!=null) {
PageSource ps = ep.getTemplate();
if(ps.physcalExists()){
Resource res = ps.getResource();
try {
String content = IOUtil.toString(res, getConfig().getTemplateCharset());
Struct sct=pe.getErrorBlock(this,ep);
java.util.Iterator<Entry<Key, Object>> it = sct.entryIterator();
Entry<Key, Object> e;
String v;
while(it.hasNext()){
e = it.next();
v=Caster.toString(e.getValue(),null);
if(v!=null)content=repl(content, e.getKey().getString(), v);
}
write(content);
return;
} catch(Throwable t) {
ExceptionUtil.rethrowIfNecessary(t);
pe=Caster.toPageException(t);
}
}
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 "+Constants.NAME+" archive (.lar), you need to use type exception instead.");
}
try {
String template=getConfig().getErrorTemplate(statusCode);
if(!StringUtil.isEmpty(template)) {
try {
Struct catchBlock=pe.getCatchBlock(getConfig());
variablesScope().setEL(KeyConstants._cfcatch,catchBlock);
variablesScope().setEL(KeyConstants._catch,catchBlock);
doInclude(template,false);
return;
}
catch (PageException e) {
pe=e;
}
}
if(!Abort.isSilentAbort(pe))forceWrite(getConfig().getDefaultDumpWriter(DumpWriter.DEFAULT_RICH).toString(this,pe.toDumpData(this, 9999,DumpUtil.toDumpProperties()),true));
}
catch (Exception e) {}
}
}
private int getStatusCode(PageException pe) {
int statusCode=500;
int maxDeepFor404=0;
if(pe instanceof ModernAppListenerException){
pe=((ModernAppListenerException)pe).getPageException();
maxDeepFor404=1;
}
else if(pe instanceof PageExceptionBox)
pe=((PageExceptionBox)pe).getPageException();
if(pe instanceof MissingIncludeException) {
MissingIncludeException mie=(MissingIncludeException) pe;
if(mie.getPageDeep()<=maxDeepFor404) statusCode=404;
}
return statusCode;
}
@Override
public void handlePageException(Exception e) {
handlePageException(Caster.toPageException(e));
}
@Override
public void handlePageException(Throwable t) {
handlePageException(Caster.toPageException(t));
}
@Override
public void setHeader(String name, String value) {
rsp.setHeader(name,value);
}
@Override
public BodyContent pushBody() {
forceWriter=bodyContentStack.push();
if(enablecfoutputonly>0 && outputState==0) {
writer=devNull;
}
else writer=forceWriter;
return (BodyContent)forceWriter;
}
@Override
public JspWriter popBody() {
forceWriter=bodyContentStack.pop();
if(enablecfoutputonly>0 && outputState==0) {
writer=devNull;
}
else writer=forceWriter;
return forceWriter;
}
@Override
public void outputStart() {
outputState++;
if(enablecfoutputonly>0 && outputState==1)writer=forceWriter;
//if(enablecfoutputonly && outputState>0) unsetDevNull();
}
@Override
public void outputEnd() {
outputState--;
if(enablecfoutputonly>0 && outputState==0)writer=devNull;
}
@Override
public void setCFOutputOnly(boolean boolEnablecfoutputonly) {
if(boolEnablecfoutputonly)this.enablecfoutputonly++;
else if(this.enablecfoutputonly>0)this.enablecfoutputonly--;
setCFOutputOnly(enablecfoutputonly);
//if(!boolEnablecfoutputonly)setCFOutputOnly(enablecfoutputonly=0);
}
@Override
public void setCFOutputOnly(short enablecfoutputonly) {
this.enablecfoutputonly=enablecfoutputonly;
if(enablecfoutputonly>0) {
if(outputState==0) writer=devNull;
}
else {
writer=forceWriter;
}
}
@Override
public boolean setSilent() {
boolean before=bodyContentStack.getDevNull();
bodyContentStack.setDevNull(true);
forceWriter = bodyContentStack.getWriter();
writer=forceWriter;
return before;
}
@Override
public boolean unsetSilent() {
boolean before=bodyContentStack.getDevNull();
bodyContentStack.setDevNull(false);
forceWriter = bodyContentStack.getWriter();
if(enablecfoutputonly>0 && outputState==0) {
writer=devNull;
}
else writer=forceWriter;
return before;
}
@Override
public Debugger getDebugger() {
return debugger;
}
@Override
public void executeRest(String realPath, boolean throwExcpetion) throws PageException {
initallog();
ApplicationListener listener=null;//config.get ApplicationListener();
try{
String pathInfo = req.getPathInfo();
// charset
try{
String charset=HTTPUtil.splitMimeTypeAndCharset(req.getContentType(),new String[]{"",""})[1];
if(StringUtil.isEmpty(charset))charset=getWebCharset().name();
java.net.URL reqURL = new java.net.URL(req.getRequestURL().toString());
String path=ReqRspUtil.decode(reqURL.getPath(),charset,true);
String srvPath=req.getServletPath();
if(path.startsWith(srvPath)) {
pathInfo=path.substring(srvPath.length());
}
}
catch (Exception e){}
// Service mapping
if(StringUtil.isEmpty(pathInfo) || pathInfo.equals("/")) {// ToDo
// list available services (if enabled in admin)
if(config.getRestList()) {
try {
HttpServletRequest _req = getHttpServletRequest();
write("Available sevice mappings are:<ul>");
lucee.runtime.rest.Mapping[] mappings = config.getRestMappings();
lucee.runtime.rest.Mapping _mapping;
String path;
for(int i=0;i<mappings.length;i++){
_mapping=mappings[i];
Resource p = _mapping.getPhysical();
path=_req.getContextPath()+ReqRspUtil.getScriptName(this,_req)+_mapping.getVirtual();
write("<li "+(p==null || !p.isDirectory()?" style=\"color:red\"":"")+">"+path+"</li>");
}
write("</ul>");
} catch (IOException e) {
throw Caster.toPageException(e);
}
}
else
RestUtil.setStatus(this, 404, null);
return;
}
// check for matrix
int index;
String entry;
Struct matrix=new StructImpl();
while((index=pathInfo.lastIndexOf(';'))!=-1){
entry=pathInfo.substring(index+1);
pathInfo=pathInfo.substring(0,index);
if(StringUtil.isEmpty(entry,true)) continue;
index=entry.indexOf('=');
if(index!=-1)matrix.setEL(KeyImpl.init(entry.substring(0,index).trim()), entry.substring(index+1).trim());
else matrix.setEL(KeyImpl.init(entry.trim()), "");
}
// get accept
List<MimeType> accept = ReqRspUtil.getAccept(this);
MimeType contentType = ReqRspUtil.getContentType(this);
// check for format extension
//int format = getApplicationContext().getRestSettings().getReturnFormat();
int format;
boolean hasFormatExtension=false;
if(StringUtil.endsWithIgnoreCase(pathInfo, ".json")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-5);
format = UDF.RETURN_FORMAT_JSON;
accept.clear();
accept.add(MimeType.APPLICATION_JSON);
hasFormatExtension=true;
}
else if(StringUtil.endsWithIgnoreCase(pathInfo, ".wddx")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-5);
format = UDF.RETURN_FORMAT_WDDX;
accept.clear();
accept.add(MimeType.APPLICATION_WDDX);
hasFormatExtension=true;
}
else if(StringUtil.endsWithIgnoreCase(pathInfo, ".cfml")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-5);
format = UDF.RETURN_FORMAT_SERIALIZE;
accept.clear();
accept.add(MimeType.APPLICATION_CFML);
hasFormatExtension=true;
}
else if(StringUtil.endsWithIgnoreCase(pathInfo, ".serialize")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-10);
format = UDF.RETURN_FORMAT_SERIALIZE;
accept.clear();
accept.add(MimeType.APPLICATION_CFML);
hasFormatExtension=true;
}
else if(StringUtil.endsWithIgnoreCase(pathInfo, ".xml")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-4);
format = UDF.RETURN_FORMAT_XML;
accept.clear();
accept.add(MimeType.APPLICATION_XML);
hasFormatExtension=true;
}
else if(StringUtil.endsWithIgnoreCase(pathInfo, ".java")) {
pathInfo=pathInfo.substring(0,pathInfo.length()-5);
format = UDFPlus.RETURN_FORMAT_JAVA;
accept.clear();
accept.add(MimeType.APPLICATION_JAVA);
hasFormatExtension=true;
}
else {
format = getApplicationContext().getRestSettings().getReturnFormat();
//MimeType mt=MimeType.toMimetype(format);
//if(mt!=null)accept.add(mt);
}
if(accept.size()==0) accept.add(MimeType.ALL);
// loop all mappings
//lucee.runtime.rest.Result result = null;//config.getRestSource(pathInfo, null);
RestRequestListener rl=null;
lucee.runtime.rest.Mapping[] restMappings = config.getRestMappings();
lucee.runtime.rest.Mapping m,mapping=null,defaultMapping=null;
//String callerPath=null;
if(restMappings!=null)for(int i=0;i<restMappings.length;i++) {
m = restMappings[i];
if(m.isDefault())defaultMapping=m;
if(pathInfo.startsWith(m.getVirtualWithSlash(),0) && m.getPhysical()!=null) {
mapping=m;
//result = m.getResult(this,callerPath=pathInfo.substring(m.getVirtual().length()),format,matrix,null);
rl=new RestRequestListener(m,pathInfo.substring(m.getVirtual().length()),matrix,format,hasFormatExtension,accept,contentType,null);
break;
}
}
// default mapping
if(mapping==null && defaultMapping!=null && defaultMapping.getPhysical()!=null) {
mapping=defaultMapping;
//result = mapping.getResult(this,callerPath=pathInfo,format,matrix,null);
rl=new RestRequestListener(mapping,pathInfo,matrix,format,hasFormatExtension,accept,contentType,null);
}
//base = PageSourceImpl.best(config.getPageSources(this,null,realPath,true,false,true));
if(mapping==null || mapping.getPhysical()==null){
RestUtil.setStatus(this,404,"no rest service for ["+pathInfo+"] found");
getConfig().getLog("rest").error("REST", "no rest service for ["+pathInfo+"] found");
}
else {
base=config.toPageSource(null, mapping.getPhysical(), null);
listener=((MappingImpl)base.getMapping()).getApplicationListener();
listener.onRequest(this, base,rl);
}
}
catch(Throwable t) {
ExceptionUtil.rethrowIfNecessary(t);
PageException pe = Caster.toPageException(t);
if(!Abort.isSilentAbort(pe)){
log(true);
if(fdEnabled){
FDSignal.signal(pe, false);
}
if(listener==null) {
if(base==null)listener=config.getApplicationListener();
else listener=((MappingImpl)base.getMapping()).getApplicationListener();
}
listener.onError(this,pe);
}
else log(false);
if(throwExcpetion) throw pe;
}
finally {
if(enablecfoutputonly>0){
setCFOutputOnly((short)0);
}
base=null;
}
}
@Override
public final void execute(String realPath, boolean throwExcpetion, boolean onlyTopLevel) throws PageException {
requestDialect=currentTemplateDialect=CFMLEngine.DIALECT_LUCEE;
_execute(realPath, throwExcpetion, onlyTopLevel);
}
@Override
public final void executeCFML(String realPath, boolean throwExcpetion, boolean onlyTopLevel) throws PageException {
requestDialect=currentTemplateDialect=CFMLEngine.DIALECT_CFML;
_execute(realPath, throwExcpetion, onlyTopLevel);
}
private final void _execute(String realPath, boolean throwExcpetion, boolean onlyTopLevel) throws PageException {
if((config.getScriptProtect()&ApplicationContext.SCRIPT_PROTECT_URL)>0) {
realPath=ScriptProtect.translate(realPath);
}
// convert realpath to a PageSource
if(realPath.startsWith("/mapping-")){
base=null;
int index = realPath.indexOf('/',9);
if(index>-1){
String type = realPath.substring(9,index);
if(type.equalsIgnoreCase("tag")){
base=getPageSource(
new Mapping[]{config.getTagMapping(),config.getServerTagMapping()},
realPath.substring(index)
);
}
else if(type.equalsIgnoreCase("customtag")){
base=getPageSource(
config.getCustomTagMappings(),
realPath.substring(index)
);
}
}
if(base==null) base=PageSourceImpl.best(config.getPageSources(this,null,realPath,onlyTopLevel,false,true));
}
else base=PageSourceImpl.best(config.getPageSources(this,null,realPath,onlyTopLevel,false,true));
execute(base, throwExcpetion, onlyTopLevel);
}
private final void execute(PageSource ps, boolean throwExcpetion, boolean onlyTopLevel) throws PageException {
ApplicationListener listener=getRequestDialect()==CFMLEngine.DIALECT_CFML?
(gatewayContext?config.getApplicationListener():((MappingImpl)ps.getMapping()).getApplicationListener())
:ModernAppListener.getInstance();
Throwable _t=null;
try {
initallog();
listener.onRequest(this,ps,null);
log(false);
}
catch(Throwable t) {
PageException pe;
if(t instanceof ThreadDeath && getTimeoutStackTrace()!=null) {
t=pe=new RequestTimeoutException(this);
}
else pe = Caster.toPageException(t,false);
_t=t;
if(!Abort.isSilentAbort(pe)){
this.pe=pe;
log(true);
if(fdEnabled){
FDSignal.signal(pe, false);
}
listener.onError(this,pe);
}
else log(false);
if(throwExcpetion) {
ExceptionUtil.rethrowIfNecessary(t);
throw pe;
}
}
finally {
if(enablecfoutputonly>0){
setCFOutputOnly((short)0);
}
if(!gatewayContext && getConfig().debug()) {
try {
listener.onDebug(this);
}
catch (Exception e) {
pe=Caster.toPageException(e);
if(!Abort.isSilentAbort(pe))listener.onError(this,pe);
ExceptionUtil.rethrowIfNecessary(e);
}
}
ps=null;
if(_t!=null)ExceptionUtil.rethrowIfNecessary(_t);
}
}
private void initallog() {
if(!isGatewayContext() && config.isMonitoringEnabled()) {
RequestMonitor[] monitors = config.getRequestMonitors();
if(monitors!=null)for(int i=0;i<monitors.length;i++){
if(monitors[i].isLogEnabled()) {
try {
((RequestMonitorPro)monitors[i]).init(this);
}
catch (Throwable e) {ExceptionUtil.rethrowIfNecessary(e);}
}
}
}
}
private void log(boolean error) {
if(!isGatewayContext() && config.isMonitoringEnabled()) {
RequestMonitor[] monitors = config.getRequestMonitors();
if(monitors!=null)for(int i=0;i<monitors.length;i++){
if(monitors[i].isLogEnabled()){
try {
monitors[i].log(this,error);
}
catch (Throwable e) {ExceptionUtil.rethrowIfNecessary(e);}
}
}
}
}
private PageSource getPageSource(Mapping[] mappings, String realPath) {
PageSource ps;
//print.err(mappings.length);
for(int i=0;i<mappings.length;i++) {
ps = mappings[i].getPageSource(realPath);
//print.err(ps.getDisplayPath());
if(ps.exists()) return ps;
}
return null;
}
@Override
public void include(String realPath) throws ServletException,IOException {
HTTPUtil.include(this, realPath);
}
@Override
public void forward(String realPath) throws ServletException, IOException {
HTTPUtil.forward(this, realPath);
}
@Override
public void clear() {
try {
//print.o(getOut().getClass().getName());
getOut().clear();
} catch (IOException e) {}
}
@Override
public long getRequestTimeout() {
if(requestTimeout==-1) {
if(applicationContext!=null) {
return applicationContext.getRequestTimeout().getMillis();
}
requestTimeout=config.getRequestTimeout().getMillis();
}
return requestTimeout;
}
@Override
public void setRequestTimeout(long requestTimeout) {
this.requestTimeout = requestTimeout;
}
@Override
public String getCFID() {
if(cfid==null) initIdAndToken();
return cfid;
}
@Override
public String getCFToken() {
if(cftoken==null) initIdAndToken();
return cftoken;
}
@Override
public String getURLToken() {
if(getConfig().getSessionType()==Config.SESSION_TYPE_JEE) {
HttpSession s = getSession();
return "CFID="+getCFID()+"&CFTOKEN="+getCFToken()+"&jsessionid="+(s!=null?getSession().getId():"");
}
return "CFID="+getCFID()+"&CFTOKEN="+getCFToken();
}
@Override
public String getJSessionId() {
if(getConfig().getSessionType()==Config.SESSION_TYPE_JEE) {
return getSession().getId();
}
return null;
}
/**
* initialize the cfid and the cftoken
*/
private void initIdAndToken() {
boolean setCookie=true;
// From URL
Object oCfid = urlScope().get(KeyConstants._cfid,null);
Object oCftoken = urlScope().get(KeyConstants._cftoken,null);
// if CFID comes from URL, we only accept if already exists
if(oCfid!=null) {
if(Decision.isGUIdSimple(oCfid)) {
if(!scopeContext.hasExistingCFID(this, Caster.toString(oCfid,null))) {
oCfid=null;
oCftoken=null;
}
}
else {
oCfid=null;
oCftoken=null;
}
}
// Cookie
if(oCfid==null) {
setCookie=false;
oCfid = cookieScope().get(KeyConstants._cfid,null);
oCftoken = cookieScope().get(KeyConstants._cftoken,null);
}
// check cookie value
if(oCfid!=null) {
// cookie value is invalid, maybe from ACF
if(!Decision.isGUIdSimple(oCfid)) {
oCfid=null;
oCftoken=null;
Charset charset = getWebCharset();
// check if we have multiple cookies with the name "cfid" and a other one is valid
javax.servlet.http.Cookie[] cookies = getHttpServletRequest().getCookies();
String name,value;
if(cookies!=null) {
for(int i=0;i<cookies.length;i++){
name=ReqRspUtil.decode(cookies[i].getName(),charset.name(),false);
// CFID
if("cfid".equalsIgnoreCase(name)) {
value=ReqRspUtil.decode(cookies[i].getValue(),charset.name(),false);
if(Decision.isGUIdSimple(value)) oCfid=value;
ReqRspUtil.removeCookie(getHttpServletResponse(),name);
}
// CFToken
else if("cftoken".equalsIgnoreCase(name)) {
value=ReqRspUtil.decode(cookies[i].getValue(),charset.name(),false);
if(isValidCfToken(value)) oCftoken=value;
ReqRspUtil.removeCookie(getHttpServletResponse(),name);
}
}
}
if(oCfid!=null) {
setCookie=true;
if(oCftoken==null)oCftoken="0";
}
}
}
// New One
if(oCfid==null || oCftoken==null) {
setCookie=true;
cfid=ScopeContext.getNewCFId();
cftoken=ScopeContext.getNewCFToken();
}
else {
cfid=Caster.toString(oCfid,null);
cftoken=Caster.toString(oCftoken,"0");
}
if(setCookie && applicationContext.isSetClientCookies())
setClientCookies();
}
private boolean isValidCfToken(String value) {
return Operator.compare(value, "0")==0;
}
public void resetIdAndToken() {
cfid=ScopeContext.getNewCFId();
cftoken=ScopeContext.getNewCFToken();
if(applicationContext.isSetClientCookies())
setClientCookies();
}
private void setClientCookies() {
TimeSpan tsExpires = SessionCookieDataImpl.DEFAULT.getTimeout();
String domain = PageContextUtil.getCookieDomain( this );
boolean httpOnly=SessionCookieDataImpl.DEFAULT.isHttpOnly();
boolean secure=SessionCookieDataImpl.DEFAULT.isSecure();
ApplicationContext ac = getApplicationContext();
if(ac instanceof ApplicationContextSupport) {
ApplicationContextSupport acs=(ApplicationContextSupport) ac;
SessionCookieData data = acs.getSessionCookie();
if(data!=null) {
// expires
TimeSpan ts = data.getTimeout();
if(ts!=null) tsExpires=ts;
// httpOnly
httpOnly=data.isHttpOnly();
// secure
secure=data.isSecure();
// domain
String tmp=data.getDomain();
if(!StringUtil.isEmpty(tmp,true)) domain=tmp.trim();
}
}
int expires;
long tmp=tsExpires.getSeconds();
if(Integer.MAX_VALUE<tmp) expires=Integer.MAX_VALUE;
else expires=(int)tmp;
cookieScope().setCookieEL( KeyConstants._cfid, cfid, expires,secure, "/", domain, httpOnly, true, false );
cookieScope().setCookieEL( KeyConstants._cftoken, cftoken, expires,secure, "/", domain, httpOnly, true, false );
}
@Override
public int getId() {
return id;
}
/**
* @return returns the root JSP Writer
*
*/
public CFMLWriter getRootOut() {// used in extension PDF
return bodyContentStack.getBase();
}
public JspWriter getRootWriter() {
return bodyContentStack.getBase();
}
@Override
public void setPsq(boolean psq) {
this.psq=psq;
}
@Override
public boolean getPsq() {
return psq;
}
@Override
public Locale getLocale() {
Locale l = getApplicationContext().getLocale();
if(l!=null) return l;
if(locale!=null) return locale;
return config.getLocale();
}
@Override
public void setLocale(Locale locale) {
getApplicationContext().setLocale(locale);
this.locale=locale;
HttpServletResponse rsp = getHttpServletResponse();
Charset charEnc = ReqRspUtil.getCharacterEncoding(this,rsp);
rsp.setLocale(locale);
if(charEnc.equals(CharsetUtil.UTF8)) {
ReqRspUtil.setContentType(rsp,"text/html; charset=UTF-8");
}
else if(!charEnc.equals(ReqRspUtil.getCharacterEncoding(this,rsp))) {
ReqRspUtil.setContentType(rsp,"text/html; charset=" + charEnc);
}
}
@Override
public void setLocale(String strLocale) throws ExpressionException {
setLocale(Caster.toLocale(strLocale));
}
@Override
public void setErrorPage(ErrorPage ep) {
errorPagePool.setErrorPage(ep);
}
// called by generated bytecode
public Tag use(String tagClassName,String fullname,int attrType) throws PageException {
return use(tagClassName, null, null, fullname, attrType);
}
// called by generated bytecode
public Tag use(String tagClassName,String tagBundleName, String tagBundleVersion, String fullname,int attrType) throws PageException {
parentTag=currentTag;
currentTag= tagHandlerPool.use(tagClassName,tagBundleName,tagBundleVersion,getConfig().getIdentification());
if(currentTag==parentTag) throw new ApplicationException("");
currentTag.setPageContext(this);
currentTag.setParent(parentTag);
if(attrType>=0 && fullname!=null) {
Map<Collection.Key, Object> attrs = applicationContext.getTagAttributeDefaultValues(this,fullname);
if(attrs!=null) {
TagUtil.setAttributes(this,currentTag, attrs, attrType);
}
}
return currentTag;
}
public void reuse(Tag tag) {
currentTag=tag.getParent();
tagHandlerPool.reuse(tag);
}
public void reuse(Tag tag,String tagBundleName, String tagBundleVersion) {
currentTag=tag.getParent();
tagHandlerPool.reuse(tag,tagBundleName,tagBundleVersion);
}
@Override
public void initBody(BodyTag bodyTag, int state) throws JspException {
if (state != Tag.EVAL_BODY_INCLUDE) {
bodyTag.setBodyContent(pushBody());
bodyTag.doInitBody();
}
}
@Override
public void releaseBody(BodyTag bodyTag, int state) {
if(bodyTag instanceof TryCatchFinally) {
((TryCatchFinally)bodyTag).doFinally();
}
if (state != Tag.EVAL_BODY_INCLUDE)popBody();
}
/* *
* @return returns the cfml compiler
* /
public CFMLCompiler getCompiler() {
return compiler;
}*/
@Override
public void setVariablesScope(Variables variables) {
this.variables=variables;
undefinedScope().setVariableScope(variables);
if(variables instanceof ClosureScope) {
variables = ((ClosureScope)variables).getVariables();
}
if(variables instanceof StaticScope){
activeComponent=((StaticScope)variables).getComponent();
}
else if(variables instanceof ComponentScope) {
activeComponent=((ComponentScope)variables).getComponent();
}
else {
activeComponent=null;
}
}
@Override
public Component getActiveComponent() {
return activeComponent;
}
@Override
public Credential getRemoteUser() throws PageException {
if(remoteUser==null) {
Key name = KeyImpl.init(Login.getApplicationName(applicationContext));
Resource roles = config.getConfigDir().getRealResource("roles");
if(applicationContext.getLoginStorage()==Scope.SCOPE_SESSION) {
Object auth = sessionScope().get(name,null);
if(auth!=null) {
remoteUser=CredentialImpl.decode(auth,roles);
}
}
else if(applicationContext.getLoginStorage()==Scope.SCOPE_COOKIE) {
Object auth = cookieScope().get(name,null);
if(auth!=null) {
remoteUser=CredentialImpl.decode(auth,roles);
}
}
}
return remoteUser;
}
@Override
public void clearRemoteUser() {
if(remoteUser!=null)remoteUser=null;
String name=Login.getApplicationName(applicationContext);
cookieScope().removeEL(KeyImpl.init(name));
try {
sessionScope().removeEL(KeyImpl.init(name));
} catch (PageException e) {}
}
@Override
public void setRemoteUser(Credential remoteUser) {
this.remoteUser = remoteUser;
}
@Override
public VariableUtil getVariableUtil() {
return variableUtil;
}
@Override
public void throwCatch() throws PageException {
if(exception!=null) throw exception;
throw new ApplicationException("invalid context for tag/script expression rethow");
}
@Override
public PageException setCatch(Throwable t) {
PageException pe=t==null?null:Caster.toPageException(t);
_setCatch(pe, false, true, false);
return pe;
}
public void setCatch(PageException pe) {
_setCatch(pe, false, true, false);
}
public void setCatch(PageException pe,boolean caught, boolean store) {
_setCatch(pe, caught, store, true);
}
public void _setCatch(PageException pe,boolean caught, boolean store, boolean signal) {
if(signal && fdEnabled){
FDSignal.signal(pe, caught);
}
exception = pe;
if(store){
Undefined u=undefinedScope();
if(pe==null) {
(u.getCheckArguments()?u.localScope():u).removeEL(KeyConstants._cfcatch);
}
else {
(u.getCheckArguments()?u.localScope():u).setEL(KeyConstants._cfcatch,pe.getCatchBlock(config));
if(!gatewayContext && config.debug() && config.hasDebugOptions(ConfigImpl.DEBUG_EXCEPTION))
debugger.addException(config,exception);
}
}
}
/**
* @return return current catch
*/
public PageException getCatch() {
return exception;
}
@Override
public void clearCatch() {
exception = null;
Undefined u=undefinedScope();
(u.getCheckArguments()?u.localScope():u).removeEL(KeyConstants._cfcatch);
}
@Override
public void addPageSource(PageSource ps, boolean alsoInclude) {
currentTemplateDialect=ps.getDialect();
pathList.add(ps);
if(alsoInclude)
includePathList.add(ps);
}
public void addPageSource(PageSource ps, PageSource psInc) {
currentTemplateDialect=ps.getDialect();
pathList.add(ps);
if(psInc!=null)
includePathList.add(psInc);
}
@Override
public void removeLastPageSource(boolean alsoInclude) {
if(!pathList.isEmpty())pathList.removeLast();
if(!pathList.isEmpty())currentTemplateDialect=pathList.getLast().getDialect();
if(alsoInclude && !includePathList.isEmpty())
includePathList.removeLast();
}
public UDF[] getUDFs() {
return udfs.toArray(new UDF[udfs.size()]);
}
public void addUDF(UDF udf) {
udfs.add(udf);
}
public void removeUDF() {
if(!udfs.isEmpty())udfs.removeLast();
}
public FTPPoolImpl getFTPPool() {
return ftpPool;
}
/* *
* @return Returns the manager.
* /
public DataSourceManager getManager() {
return manager;
}*/
@Override
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
session=null;
application=null;
client=null;
this.applicationContext = applicationContext;
int scriptProtect = applicationContext.getScriptProtect();
// ScriptProtecting
if(config.mergeFormAndURL()) {
form.setScriptProtecting(applicationContext,
(scriptProtect&ApplicationContext.SCRIPT_PROTECT_FORM)>0
||
(scriptProtect&ApplicationContext.SCRIPT_PROTECT_URL)>0);
}
else {
form.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_FORM)>0);
url.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_URL)>0);
}
cookie.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_COOKIE)>0);
// CGI
cgiR.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_CGI)>0);
cgiRW.setScriptProtecting(applicationContext,(scriptProtect&ApplicationContext.SCRIPT_PROTECT_CGI)>0);
undefined.reinitialize(this);
}
/**
* @return return value of method "onApplicationStart" or true
* @throws PageException
*/
public boolean initApplicationContext(ApplicationListener listener) throws PageException {
boolean initSession=false;
//AppListenerSupport listener = (AppListenerSupport) config.get ApplicationListener();
KeyLock<String> lock = config.getContextLock();
String name=StringUtil.emptyIfNull(applicationContext.getName());
String token=name+":"+getCFID();
Lock tokenLock = lock.lock(token,getRequestTimeout());
//print.o("outer-lock :"+token);
try {
// check session before executing any code
initSession=applicationContext.isSetSessionManagement() && listener.hasOnSessionStart(this) && !scopeContext.hasExistingSessionScope(this);
// init application
Lock nameLock = lock.lock(name,getRequestTimeout());
//print.o("inner-lock :"+token);
try {
RefBoolean isNew=new RefBooleanImpl(false);
application=scopeContext.getApplicationScope(this,isNew);// this is needed that the application scope is initilized
if(isNew.toBooleanValue()) {
try {
if(!listener.onApplicationStart(this)) {
scopeContext.removeApplicationScope(this);
return false;
}
} catch (PageException pe) {
scopeContext.removeApplicationScope(this);
throw pe;
}
}
}
finally{
//print.o("inner-unlock:"+token);
lock.unlock(nameLock);
}
// init session
if(initSession) {
scopeContext.getSessionScope(this, DUMMY_BOOL);// this is needed that the session scope is initilized
listener.onSessionStart(this);
}
}
finally{
//print.o("outer-unlock:"+token);
lock.unlock(tokenLock);
}
return true;
}
/**
* @return the scope factory
*/
public ScopeFactory getScopeFactory() {
return scopeFactory;
}
@Override
public Tag getCurrentTag() {
return currentTag;
}
@Override
public long getStartTime() {
return startTime;
}
@Override
public Thread getThread() {
return thread;
}
public void setThread(Thread thread) {
this.thread=thread;
}
@Override
public long getExecutionTime() {
return executionTime;
}
@Override
public void setExecutionTime(long executionTime) {
this.executionTime = executionTime;
}
@Override
public synchronized void compile(PageSource pageSource) throws PageException {
Resource classRootDir = pageSource.getMapping().getClassRootDirectory();
int dialect=getCurrentTemplateDialect();
try {
config.getCompiler().compile(
config,
pageSource,
config.getTLDs(dialect),
config.getFLDs(dialect),
classRootDir,false,ignoreScopes()
);
} catch (Exception e) {
throw Caster.toPageException(e);
}
}
@Override
public void compile(String realPath) throws PageException {
SystemOut.printDate("method PageContext.compile(String) should no longer be used!");
compile(PageSourceImpl.best(getRelativePageSources(realPath)));
}
public HttpServlet getServlet() {
return servlet;
}
@Override
public lucee.runtime.Component loadComponent(String compPath) throws PageException {
return ComponentLoader.searchComponent(this,null,compPath,null,null,false);
}
/**
* @return the base
*/
public PageSource getBase() {
return base;
}
/**
* @param base the base to set
*/
public void setBase(PageSource base) {
this.base = base;
}
@Override
public DataSourceManager getDataSourceManager() {
return manager;
}
@Override
public Object evaluate(String expression) throws PageException {
return new CFMLExpressionInterpreter(false).interpret(this,expression);
}
@Override
public String serialize(Object expression) throws PageException {
return Serialize.call(this, expression);
}
/**
* @return the activeUDF
*/
public UDF getActiveUDF() {
return activeUDF;
}
public Collection.Key getActiveUDFCalledName() {
return activeUDFCalledName;
}
public void setActiveUDFCalledName(Collection.Key activeUDFCalledName) {
this.activeUDFCalledName=activeUDFCalledName;
}
/**
* @param activeUDF the activeUDF to set
*/
public void setActiveUDF(UDF activeUDF) {
this.activeUDF = activeUDF;
}
@Override
public CFMLFactory getCFMLFactory() {
return config.getFactory();
}
@Override
public PageContext getParentPageContext() {
return parent;
}
public List<PageContext> getChildPageContexts() {
return children;
}
@Override
public String[] getThreadScopeNames() {
if(threads==null)return new String[0];
return CollectionUtil.keysAsString(threads);
}
@Override
public Threads getThreadScope(String name) {
return getThreadScope(KeyImpl.init(name));
}
public Threads getThreadScope(Collection.Key name) {// MUST who uses this? is cfthread/thread handling necessary
if(threads==null)threads=new StructImpl();
Object obj = threads.get(name,null);
if(obj instanceof Threads)return (Threads) obj;
return null;
}
public Object getThreadScope(Collection.Key name,Object defaultValue) {
if(threads==null)threads=new StructImpl();
if(name.equalsIgnoreCase(KeyConstants._cfthread)) return threads; // do not change this, this is used!
if(name.equalsIgnoreCase(KeyConstants._thread)) {
ThreadsImpl curr = getCurrentThreadScope();
if(curr!=null) return curr;
}
return threads.get(name,defaultValue);
}
public void setCurrentThreadScope(ThreadsImpl thread) {
currentThread=thread;
}
public ThreadsImpl getCurrentThreadScope() {
return currentThread;
}
@Override
public void setThreadScope(String name,Threads ct) {
setThreadScope(KeyImpl.init(name), ct);
}
public void setThreadScope(Collection.Key name,Threads ct) {
hasFamily=true;
if(threads==null) threads=new StructImpl();
threads.setEL(name, ct);
}
@Override
public boolean hasFamily() {
return hasFamily;
}
@Override
public TimeZone getTimeZone() {
TimeZone tz = getApplicationContext().getTimeZone();
if(tz!=null) return tz;
if(timeZone!=null) return timeZone;
return config.getTimeZone();
}
@Override
public void setTimeZone(TimeZone timeZone) {
getApplicationContext().setTimeZone(timeZone);
this.timeZone=timeZone;
}
/**
* @return the requestId
*/
public int getRequestId() {
return requestId;
}
private Set<String> pagesUsed=new HashSet<String>();
private Stack<ActiveQuery> activeQueries=new Stack<ActiveQuery>();
private Stack<ActiveLock> activeLocks=new Stack<ActiveLock>();
private boolean literalTimestampWithTSOffset;
public boolean isTrusted(Page page) {
if(page==null)return false;
short it = ((MappingImpl)page.getPageSource().getMapping()).getInspectTemplate();
if(it==ConfigImpl.INSPECT_NEVER)return true;
if(it==ConfigImpl.INSPECT_ALWAYS)return false;
return pagesUsed.contains(""+page.hashCode());
}
public void setPageUsed(Page page) {
pagesUsed.add(""+page.hashCode());
}
@Override
public void exeLogStart(int position,String id){
if(execLog!=null)execLog.start(position, id);
}
@Override
public void exeLogEnd(int position,String id){
if(execLog!=null)execLog.end(position, id);
}
@Override
public ORMSession getORMSession(boolean create) throws PageException {
if(ormSession==null || !ormSession.isValid()) {
if(!create) return null;
ormSession=config.getORMEngine(this).createSession(this);
}
DatasourceManagerImpl manager = (DatasourceManagerImpl) getDataSourceManager();
manager.add(this,ormSession);
return ormSession;
}
public ClassLoader getClassLoader() throws IOException {
return getResourceClassLoader();
}
public ClassLoader getClassLoader(Resource[] reses) throws IOException{
return getResourceClassLoader().getCustomResourceClassLoader(reses);
}
private ResourceClassLoader getResourceClassLoader() throws IOException {
JavaSettingsImpl js = (JavaSettingsImpl) applicationContext.getJavaSettings();
if(js!=null) {
return config.getResourceClassLoader().getCustomResourceClassLoader(js.getResourcesTranslated());
}
return config.getResourceClassLoader();
}
public ClassLoader getRPCClassLoader(boolean reload) throws IOException {
return getRPCClassLoader(reload, null);
}
public ClassLoader getRPCClassLoader(boolean reload, ClassLoader[] parents) throws IOException {
JavaSettingsImpl js = (JavaSettingsImpl) applicationContext.getJavaSettings();
ClassLoader cl=config.getRPCClassLoader(reload,parents);
if(js!=null) {
return ((PhysicalClassLoader)cl).getCustomClassLoader(js.getResourcesTranslated(),reload);
}
return cl;
}
public void resetSession() {
this.session=null;
}
/**
* @return the gatewayContext
*/
public boolean isGatewayContext() {
return gatewayContext;
}
/**
* @param gatewayContext the gatewayContext to set
*/
public void setGatewayContext(boolean gatewayContext) {
this.gatewayContext = gatewayContext;
}
public void setServerPassword(Password serverPassword) {
this.serverPassword=serverPassword;
}
public Password getServerPassword() {
return serverPassword;
}
public short getSessionType() {
if(isGatewayContext())return Config.SESSION_TYPE_APPLICATION;
return applicationContext.getSessionType();
}
// this is just a wrapper method for ACF
public Scope SymTab_findBuiltinScope(String name) throws PageException {
return scope(name, null);
}
@Override
public DataSource getDataSource(String datasource) throws PageException {
DataSource ds = getApplicationContext().getDataSource(datasource,null);
if(ds!=null) return ds;
ds=getConfig().getDataSource(datasource,null);
if(ds!=null) return ds;
throw DatabaseException.notFoundException(this, datasource);
}
@Override
public DataSource getDataSource(String datasource, DataSource defaultValue) {
DataSource ds = getApplicationContext().getDataSource(datasource,null);
if(ds==null) ds=getConfig().getDataSource(datasource,defaultValue);
return ds;
}
public CacheConnection getCacheConnection(String cacheName, CacheConnection defaultValue) {
cacheName=cacheName.toLowerCase().trim();
CacheConnection cc=null;
if(getApplicationContext()!=null)cc = ((ApplicationContextSupport)getApplicationContext()).getCacheConnection(cacheName,null);
if(cc==null) cc= config.getCacheConnections().get(cacheName);
if(cc==null) return defaultValue;
return cc;
}
public CacheConnection getCacheConnection(String cacheName) throws CacheException {
cacheName=cacheName.toLowerCase().trim();
CacheConnection cc=null;
if(getApplicationContext()!=null) cc = ((ApplicationContextSupport)getApplicationContext()).getCacheConnection(cacheName,null);
if(cc==null) cc= config.getCacheConnections().get(cacheName);
if(cc==null) throw CacheUtil.noCache(config,cacheName);
return cc;
}
public void setActiveQuery(ActiveQuery activeQuery) {
this.activeQueries.add(activeQuery);
}
public ActiveQuery[] getActiveQueries() {
return activeQueries.toArray(new ActiveQuery[activeQueries.size()]);
}
public ActiveQuery releaseActiveQuery() {
return activeQueries.pop();
}
public void setActiveLock(ActiveLock activeLock) {
this.activeLocks.add(activeLock);
}
public ActiveLock[] getActiveLocks() {
return activeLocks.toArray(new ActiveLock[activeLocks.size()]);
}
public ActiveLock releaseActiveLock() {
return activeLocks.pop();
}
public PageException getPageException() {
return pe;
}
@Override
public Charset getResourceCharset() {
Charset cs = getApplicationContext().getResourceCharset();
if(cs!=null) return cs;
return config.getResourceCharset();
}
@Override
public Charset getWebCharset() {
Charset cs = getApplicationContext().getWebCharset();
if(cs!=null) return cs;
return config.getWebCharset();
}
public short getScopeCascadingType() {
if(applicationContext==null) return config.getScopeCascadingType();
return applicationContext.getScopeCascading();
}
public boolean getTypeChecking() {
if(applicationContext==null) return config.getTypeChecking();
return applicationContext.getTypeChecking();
}
public boolean getAllowCompression() {
if(applicationContext==null) return config.allowCompression();
return applicationContext.getAllowCompression();
}
public boolean getSuppressContent() {
if(applicationContext==null) return config.isSuppressContent();
return applicationContext.getSuppressContent();
}
@Override
public Object getCachedWithin(int type) {
if(applicationContext==null) return config.getCachedWithin(type);
return applicationContext.getCachedWithin(type);
}
// FUTURE add to interface
public lucee.runtime.net.mail.Server[] getMailServers() {
if(applicationContext!=null) {
lucee.runtime.net.mail.Server[] appms = ((ApplicationContextSupport)applicationContext).getMailServers();
if(ArrayUtil.isEmpty(appms)) return config.getMailServers();
lucee.runtime.net.mail.Server[] cms=config.getMailServers();
if(ArrayUtil.isEmpty(cms)) return appms;
lucee.runtime.net.mail.Server[] arr = ServerImpl.merge(appms, cms);
return arr;
}
return config.getMailServers();
}
public void registerLazyStatement(Statement s) {
if(lazyStats==null)lazyStats=new ArrayList<Statement>();
lazyStats.add(s);
}
@Override
public int getCurrentTemplateDialect() {
return currentTemplateDialect;
}
@Override
public int getRequestDialect() {
return requestDialect;
}
@Override
public void include(String realPath, boolean flush) throws ServletException, IOException {
include(realPath);
if(flush)flush();
}
@Override
public ExpressionEvaluator getExpressionEvaluator() {
throw new RuntimeException("not supported!");
}
@Override
public VariableResolver getVariableResolver() {
throw new RuntimeException("not supported!");
}
public ELContext getELContext() {
throw new RuntimeException("not supported!");
}
@Override
public boolean ignoreScopes() {
return ignoreScopes;
}
public void setIgnoreScopes(boolean ignoreScopes) {
this.ignoreScopes=ignoreScopes;
}
public void setAppListenerType(int appListenerType) {
this.appListenerType=appListenerType;
}
public int getAppListenerType() {
return appListenerType;
}
public Log getLog(String name) {
return config.getLog(name);
}
public Log getLog(String name, boolean createIfNecessary) {
if(applicationContext!=null) {
Log log=((ApplicationContextSupport)applicationContext).getLog(name);
if(log!=null)return log;
}
return config.getLog(name,createIfNecessary);
}
public java.util.Collection<String> getLogNames() {
java.util.Collection<String> cnames=config.getLoggers().keySet();
if(applicationContext!=null) {
java.util.Collection<Collection.Key> anames=((ApplicationContextSupport)applicationContext).getLogNames();
java.util.Collection<String> names=new HashSet<String>();
copy(cnames,names);
copy(anames,names);
return names;
}
return cnames;
}
private void copy(java.util.Collection src, java.util.Collection<String> trg) {
java.util.Iterator it = src.iterator();
while(it.hasNext()) {
trg.add(it.next().toString());
}
}
public void setTimestampWithTSOffset(boolean literalTimestampWithTSOffset) {
this.literalTimestampWithTSOffset=literalTimestampWithTSOffset;
}
public boolean getTimestampWithTSOffset() {
return literalTimestampWithTSOffset;
}
}