001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.tag; 020 021import java.nio.charset.Charset; 022import java.util.Locale; 023import java.util.TimeZone; 024 025import lucee.commons.date.TimeZoneUtil; 026import lucee.commons.io.CharsetUtil; 027import lucee.commons.io.res.Resource; 028import lucee.commons.io.res.util.ResourceUtil; 029import lucee.commons.lang.ClassException; 030import lucee.commons.lang.StringUtil; 031import lucee.runtime.Mapping; 032import lucee.runtime.config.Config; 033import lucee.runtime.config.ConfigWebUtil; 034import lucee.runtime.exp.ApplicationException; 035import lucee.runtime.exp.ExpressionException; 036import lucee.runtime.exp.PageException; 037import lucee.runtime.ext.tag.TagImpl; 038import lucee.runtime.i18n.LocaleFactory; 039import lucee.runtime.listener.AppListenerUtil; 040import lucee.runtime.listener.ApplicationContextPro; 041import lucee.runtime.listener.ClassicApplicationContext; 042import lucee.runtime.op.Caster; 043import lucee.runtime.orm.ORMUtil; 044import lucee.runtime.type.Struct; 045import lucee.runtime.type.StructImpl; 046import lucee.runtime.type.UDF; 047import lucee.runtime.type.dt.TimeSpan; 048import lucee.runtime.type.scope.Scope; 049import lucee.runtime.type.scope.UndefinedImpl; 050 051/** 052* Defines scoping for a CFML application, enables or disables storing client variables, 053* and specifies a client variable storage mechanism. 054* By default, client variables are disabled. Also, enables session variables and sets timeouts 055* for session and application variables. Session and application variables are stored in memory. 056* 057* 058* 059**/ 060public final class Application extends TagImpl { 061 062 063 064 private static final int ACTION_CREATE = 0; 065 private static final int ACTION_UPDATE = 1; 066 067 private Boolean setClientCookies; 068 private Boolean setDomainCookies; 069 private Boolean setSessionManagement; 070 private String clientstorage; 071 private String sessionstorage; 072 private Boolean setClientManagement; 073 private TimeSpan applicationTimeout; 074 private TimeSpan sessionTimeout; 075 private TimeSpan clientTimeout; 076 private TimeSpan requestTimeout; 077 private Mapping[] mappings; 078 private Mapping[] customTagMappings; 079 private Mapping[] componentMappings; 080 private String secureJsonPrefix; 081 private Boolean bufferOutput; 082 private Boolean secureJson; 083 private String scriptrotect; 084 private Boolean typeChecking; 085 private Object datasource; 086 private Object defaultdatasource; 087 private int loginstorage=Scope.SCOPE_UNDEFINED; 088 089 //ApplicationContextImpl appContext; 090 private String name=""; 091 private int action=ACTION_CREATE; 092 private int localMode=-1; 093 private Locale locale; 094 private TimeZone timeZone; 095 private Charset webCharset; 096 private Charset resourceCharset; 097 private short sessionType=-1; 098 private short wsType=-1; 099 private boolean sessionCluster; 100 private boolean clientCluster; 101 private Boolean compression; 102 103 private Boolean ormenabled; 104 private Struct ormsettings; 105 private Struct tag; 106 private Struct s3; 107 108 private Boolean triggerDataMember=null; 109 private String cacheFunction; 110 private String cacheQuery; 111 private String cacheTemplate; 112 private String cacheInclude; 113 private String cacheObject; 114 private String cacheResource; 115 private Struct datasources; 116 private UDF onmissingtemplate; 117 private short scopeCascading=-1; 118 private Boolean suppress; 119 private boolean cgiReadOnly=true; 120 121 122 @Override 123 public void release() { 124 super.release(); 125 setClientCookies=null; 126 setDomainCookies=null; 127 setSessionManagement=null; 128 clientstorage=null; 129 sessionstorage=null; 130 setClientManagement=null; 131 sessionTimeout=null; 132 clientTimeout=null; 133 requestTimeout=null; 134 applicationTimeout=null; 135 mappings=null; 136 customTagMappings=null; 137 componentMappings=null; 138 bufferOutput=null; 139 secureJson=null; 140 secureJsonPrefix=null; 141 typeChecking=null; 142 suppress=null; 143 loginstorage=Scope.SCOPE_UNDEFINED; 144 scriptrotect=null; 145 datasource=null; 146 defaultdatasource=null; 147 datasources=null; 148 this.name=""; 149 action=ACTION_CREATE; 150 localMode=-1; 151 locale=null; 152 timeZone=null; 153 webCharset=null; 154 resourceCharset=null; 155 sessionType=-1; 156 wsType=-1; 157 sessionCluster=false; 158 clientCluster=false; 159 compression=null; 160 161 ormenabled=null; 162 ormsettings=null; 163 tag=null; 164 s3=null; 165 //appContext=null; 166 167 triggerDataMember=null; 168 cgiReadOnly=true; 169 170 cacheFunction=null; 171 cacheQuery=null; 172 cacheTemplate=null; 173 cacheObject=null; 174 cacheResource=null; 175 cacheInclude=null; 176 onmissingtemplate=null; 177 scopeCascading=-1; 178 } 179 180 /** set the value setclientcookies 181 * Yes or No. Yes enables client cookies. Default is Yes. If you set this attribute to 182 * "No", CFML does not automatically send the CFID and CFTOKEN cookies to the client browser; 183 * you must manually code CFID and CFTOKEN on the URL for every page that uses Session or Client variables. 184 * @param setClientCookies value to set 185 **/ 186 public void setSetclientcookies(boolean setClientCookies) { 187 this.setClientCookies=setClientCookies?Boolean.TRUE:Boolean.FALSE; 188 //getAppContext().setSetClientCookies(setClientCookies); 189 } 190 191 /** set the value setdomaincookies 192 * Yes or No. Sets the CFID and CFTOKEN cookies for a domain, not just a single host. 193 * Applications that are running on clusters must set this value to Yes. The default is No. 194 * @param setDomainCookies value to set 195 **/ 196 public void setSetdomaincookies(boolean setDomainCookies) { 197 this.setDomainCookies=setDomainCookies?Boolean.TRUE:Boolean.FALSE; 198 } 199 200 public void setCgireadonly(boolean cgiReadOnly) { 201 this.cgiReadOnly=cgiReadOnly; 202 } 203 204 /** set the value sessionmanagement 205 * Yes or No. Yes enables session variables. Default is No. 206 * @param setSessionManagement value to set 207 **/ 208 public void setSessionmanagement(boolean setSessionManagement) { 209 this.setSessionManagement=setSessionManagement?Boolean.TRUE:Boolean.FALSE; 210 //getAppContext().setSetSessionManagement(setSessionManagement); 211 } 212 213 214 /** 215 * @param datasource the datasource to set 216 * @throws PageException 217 */ 218 public void setDatasource(Object datasource) throws PageException { 219 this.datasource = AppListenerUtil.toDefaultDatasource(datasource); 220 } 221 222 public void setDefaultdatasource(Object defaultdatasource) throws PageException { 223 this.defaultdatasource = AppListenerUtil.toDefaultDatasource(defaultdatasource); 224 } 225 226 public void setDatasources(Struct datasources) { 227 this.datasources = datasources; 228 } 229 230 public void setLocalmode(String strLocalMode) throws ApplicationException { 231 this.localMode = AppListenerUtil.toLocalMode(strLocalMode); 232 233 } 234 235 public void setTimezone(String strTimeZone) throws ExpressionException { 236 if(StringUtil.isEmpty(strTimeZone)) return; 237 this.timeZone = TimeZoneUtil.toTimeZone(strTimeZone); 238 239 } 240 241 public void setScopecascading(String scopeCascading) throws ApplicationException { 242 if(StringUtil.isEmpty(scopeCascading)) return; 243 short NULL=-1; 244 short tmp = ConfigWebUtil.toScopeCascading(scopeCascading,NULL); 245 if(tmp==NULL) throw new ApplicationException("invalid value ("+scopeCascading+") for attribute [ScopeCascading], valid values are [strict,small,standard]"); 246 this.scopeCascading=tmp; 247 } 248 249 public void setWebcharset(String charset) { 250 if(StringUtil.isEmpty(charset)) return; 251 webCharset = CharsetUtil.toCharset(charset); 252 253 } 254 255 public void setResourcecharset(String charset) { 256 if(StringUtil.isEmpty(charset)) return; 257 resourceCharset = CharsetUtil.toCharset(charset); 258 259 } 260 261 public void setLocale(String strLocale) throws ExpressionException { 262 if(StringUtil.isEmpty(strLocale)) return; 263 this.locale = LocaleFactory.getLocale(strLocale); 264 265 } 266 267 /** set the value clientstorage 268 * Specifies how Lucee stores client variables 269 * @param clientstorage value to set 270 **/ 271 public void setClientstorage(String clientstorage) { 272 this.clientstorage=clientstorage; 273 } 274 275 public void setSessionstorage(String sessionstorage) { 276 this.sessionstorage=sessionstorage; 277 } 278 279 /** set the value clientmanagement 280 * Yes or No. Enables client variables. Default is No. 281 * @param setClientManagement value to set 282 **/ 283 public void setClientmanagement(boolean setClientManagement) { 284 this.setClientManagement=setClientManagement?Boolean.TRUE:Boolean.FALSE; 285 //getAppContext().setSetClientManagement(setClientManagement); 286 } 287 288 /** set the value sessiontimeout 289 * Enter the CreateTimeSpan function and values in days, hours, minutes, and seconds, separated 290 * by commas, to specify the lifespan of session variables. 291 * @param sessionTimeout value to set 292 **/ 293 public void setSessiontimeout(TimeSpan sessionTimeout) { 294 this.sessionTimeout=sessionTimeout; 295 } 296 public void setSessiontype(String sessionType) throws ApplicationException { 297 this.sessionType=AppListenerUtil.toSessionType(sessionType); 298 } 299 public void setWstype(String wstype) throws ApplicationException { 300 this.wsType=AppListenerUtil.toWSType(wstype); 301 } 302 public void setClientcluster(boolean clientCluster) { 303 this.clientCluster=clientCluster; 304 } 305 public void setSessioncluster(boolean sessionCluster) { 306 this.sessionCluster=sessionCluster; 307 } 308 309 public void setClienttimeout(TimeSpan clientTimeout) { 310 this.clientTimeout=clientTimeout; 311 } 312 313 public void setRequesttimeout(TimeSpan requestTimeout) { 314 this.requestTimeout=requestTimeout; 315 } 316 317 318 public void setCachefunction(String cacheFunction) { 319 if(StringUtil.isEmpty(cacheFunction,true)) return; 320 this.cacheFunction=cacheFunction.trim(); 321 } 322 public void setCachequery(String cacheQuery) { 323 if(StringUtil.isEmpty(cacheQuery,true)) return; 324 this.cacheQuery=cacheQuery.trim(); 325 } 326 public void setCachetemplate(String cacheTemplate) { 327 if(StringUtil.isEmpty(cacheTemplate,true)) return; 328 this.cacheTemplate=cacheTemplate.trim(); 329 } 330 public void setCacheinclude(String cacheInclude) { 331 if(StringUtil.isEmpty(cacheInclude,true)) return; 332 this.cacheInclude=cacheInclude.trim(); 333 } 334 public void setCacheobject(String cacheObject) { 335 if(StringUtil.isEmpty(cacheObject,true)) return; 336 this.cacheObject=cacheObject.trim(); 337 } 338 public void setCacheresource(String cacheResource) { 339 if(StringUtil.isEmpty(cacheResource,true)) return; 340 this.cacheResource=cacheResource.trim(); 341 } 342 public void setCompression(boolean compress) { 343 this.compression=compress; 344 } 345 346 347 public void setTriggerdatamember(boolean triggerDataMember) { 348 this.triggerDataMember=triggerDataMember?Boolean.TRUE:Boolean.FALSE; 349 } 350 public void setInvokeimplicitaccessor(boolean invokeimplicitaccessor) { 351 setTriggerdatamember(invokeimplicitaccessor); 352 } 353 354 /** 355 * @param ormenabled the ormenabled to set 356 */ 357 public void setOrmenabled(boolean ormenabled) { 358 this.ormenabled = ormenabled; 359 } 360 361 /** 362 * @param ormsettings the ormsettings to set 363 */ 364 public void setOrmsettings(Struct ormsettings) { 365 this.ormsettings = ormsettings; 366 } 367 public void setTag(Struct tag) { 368 this.tag = tag; 369 } 370 371 /** 372 * @param s3 the s3 to set 373 */ 374 public void setS3(Struct s3) { 375 this.s3 = s3; 376 } 377 378 /** set the value applicationtimeout 379 * Enter the CreateTimeSpan function and values in days, hours, minutes, and seconds, separated 380 * by commas, to specify the lifespan of application variables. 381 * @param applicationTimeout value to set 382 **/ 383 public void setApplicationtimeout(TimeSpan applicationTimeout) { 384 this.applicationTimeout=applicationTimeout; 385 //getAppContext().setApplicationTimeout(applicationTimeout); 386 } 387 388 /** set the value name 389 * The name of your application. This name can be up to 64 characters long. 390 * Required for application and session variables, optional for client variables 391 * @param name value to set 392 **/ 393 public void setName(String name) { 394 this.name=name; 395 } 396 397 public void setAction(String strAction) throws ApplicationException { 398 strAction=strAction.toLowerCase(); 399 if(strAction.equals("create"))action=ACTION_CREATE; 400 else if(strAction.equals("update")) action=ACTION_UPDATE; 401 else throw new ApplicationException("invalid action definition ["+strAction+"] for tag application, valid values are [create,update]"); 402 403 } 404 405 public void setMappings(Struct mappings) throws PageException { 406 this.mappings=AppListenerUtil.toMappings(pageContext.getConfig(), mappings,getSource()); 407 //getAppContext().setMappings(AppListenerUtil.toMappings(pageContext, mappings)); 408 } 409 410 public void setCustomtagpaths(Object mappings) throws PageException { 411 this.customTagMappings=AppListenerUtil.toCustomTagMappings(pageContext.getConfig(), mappings,getSource()); 412 } 413 414 public void setComponentpaths(Object mappings) throws PageException { 415 this.componentMappings=AppListenerUtil.toComponentMappings(pageContext.getConfig(), mappings,getSource()); 416 } 417 418 419 public void setSecurejsonprefix(String secureJsonPrefix) { 420 this.secureJsonPrefix=secureJsonPrefix; 421 //getAppContext().setSecureJsonPrefix(secureJsonPrefix); 422 } 423 public void setSecurejson(boolean secureJson) { 424 this.secureJson=secureJson?Boolean.TRUE:Boolean.FALSE; 425 //getAppContext().setSecureJson(secureJson); 426 } 427 public void setBufferoutput(boolean bufferOutput) { 428 this.bufferOutput=bufferOutput?Boolean.TRUE:Boolean.FALSE; 429 //getAppContext().setSecureJson(secureJson); 430 } 431 432 /** 433 * @param loginstorage The loginstorage to set. 434 * @throws ApplicationException 435 */ 436 public void setLoginstorage(String loginstorage) throws ApplicationException { 437 loginstorage=loginstorage.toLowerCase(); 438 if(loginstorage.equals("session"))this.loginstorage=Scope.SCOPE_SESSION; 439 else if(loginstorage.equals("cookie"))this.loginstorage=Scope.SCOPE_COOKIE; 440 else throw new ApplicationException("invalid loginStorage definition ["+loginstorage+"] for tag application, valid values are [session,cookie]"); 441 } 442 /** 443 * @param scriptrotect the scriptrotect to set 444 */ 445 public void setScriptprotect(String strScriptrotect) { 446 this.scriptrotect=strScriptrotect; 447 } 448 449 public void setTypechecking(boolean typeChecking) { 450 this.typeChecking=typeChecking; 451 } 452 453 public void setSuppressremotecomponentcontent(boolean suppress) { 454 this.suppress=suppress; 455 } 456 457 public void setOnmissingtemplate(Object oUDF) throws PageException { 458 this.onmissingtemplate=Caster.toFunction(oUDF); 459 } 460 461 @Override 462 public int doStartTag() throws PageException { 463 464 ApplicationContextPro ac; 465 boolean initORM; 466 if(action==ACTION_CREATE){ 467 ac=new ClassicApplicationContext(pageContext.getConfig(),name,false, 468 pageContext.getCurrentPageSource().getResourceTranslated(pageContext)); 469 initORM=set(ac,false); 470 pageContext.setApplicationContext(ac); 471 } 472 else { 473 ac=(ApplicationContextPro) pageContext.getApplicationContext(); 474 initORM=set(ac,true); 475 } 476 477 // scope cascading 478 if(((UndefinedImpl)pageContext.undefinedScope()).getScopeCascadingType()!=ac.getScopeCascading()) { 479 pageContext.undefinedScope().initialize(pageContext); 480 } 481 482 // ORM 483 if(initORM) ORMUtil.resetEngine(pageContext,false); 484 485 return SKIP_BODY; 486 } 487 488 private Resource getSource() throws PageException { 489 return ResourceUtil.getResource(pageContext,pageContext.getCurrentPageSource()); 490 } 491 492 private boolean set(ApplicationContextPro ac, boolean update) throws PageException { 493 if(applicationTimeout!=null) ac.setApplicationTimeout(applicationTimeout); 494 if(sessionTimeout!=null) ac.setSessionTimeout(sessionTimeout); 495 if(clientTimeout!=null) ac.setClientTimeout(clientTimeout); 496 if(requestTimeout!=null) ac.setRequestTimeout(requestTimeout); 497 if(clientstorage!=null) { 498 ac.setClientstorage(clientstorage); 499 } 500 if(sessionstorage!=null) { 501 ac.setSessionstorage(sessionstorage); 502 } 503 if(customTagMappings!=null) ac.setCustomTagMappings(customTagMappings); 504 if(componentMappings!=null) ac.setComponentMappings(componentMappings); 505 if(mappings!=null) ac.setMappings(mappings); 506 if(loginstorage!=Scope.SCOPE_UNDEFINED) ac.setLoginStorage(loginstorage); 507 if(!StringUtil.isEmpty(datasource)) { 508 ac.setDefDataSource(datasource); 509 ac.setORMDataSource(datasource); 510 } 511 if(!StringUtil.isEmpty(defaultdatasource))ac.setDefDataSource(defaultdatasource); 512 if(datasources!=null){ 513 try { 514 ac.setDataSources(AppListenerUtil.toDataSources(datasources)); 515 } 516 catch (ClassException e) { 517 throw Caster.toPageException(e); 518 } 519 } 520 521 if(onmissingtemplate!=null && ac instanceof ClassicApplicationContext){ 522 ((ClassicApplicationContext)ac).setOnMissingTemplate(onmissingtemplate); 523 } 524 525 if(scriptrotect!=null) ac.setScriptProtect(AppListenerUtil.translateScriptProtect(scriptrotect)); 526 if(bufferOutput!=null) ac.setBufferOutput(bufferOutput.booleanValue()); 527 if(secureJson!=null) ac.setSecureJson(secureJson.booleanValue()); 528 if(typeChecking!=null) ac.setTypeChecking(typeChecking.booleanValue()); 529 if(suppress!=null) ac.setSuppressContent(suppress.booleanValue()); 530 if(secureJsonPrefix!=null) ac.setSecureJsonPrefix(secureJsonPrefix); 531 if(setClientCookies!=null) ac.setSetClientCookies(setClientCookies.booleanValue()); 532 if(setClientManagement!=null) ac.setSetClientManagement(setClientManagement.booleanValue()); 533 if(setDomainCookies!=null) ac.setSetDomainCookies(setDomainCookies.booleanValue()); 534 if(setSessionManagement!=null) ac.setSetSessionManagement(setSessionManagement.booleanValue()); 535 if(localMode!=-1) ac.setLocalMode(localMode); 536 if(locale!=null) ac.setLocale(locale); 537 if(timeZone!=null) ac.setTimeZone(timeZone); 538 if(webCharset!=null) ac.setWebCharset(webCharset); 539 if(resourceCharset!=null) ac.setResourceCharset(resourceCharset); 540 if(sessionType!=-1) ac.setSessionType(sessionType); 541 if(wsType!=-1) ac.setWSType(wsType); 542 if(triggerDataMember!=null) ac.setTriggerComponentDataMember(triggerDataMember.booleanValue()); 543 if(compression!=null) ac.setAllowCompression(compression.booleanValue()); 544 if(cacheFunction!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_FUNCTION, cacheFunction); 545 if(cacheObject!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_OBJECT, cacheObject); 546 if(cacheQuery!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_QUERY, cacheQuery); 547 if(cacheResource!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_RESOURCE, cacheResource); 548 if(cacheTemplate!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_TEMPLATE, cacheTemplate); 549 if(cacheInclude!=null) ac.setDefaultCacheName(Config.CACHE_DEFAULT_INCLUDE, cacheInclude); 550 if(tag!=null) ac.setTagAttributeDefaultValues(tag); 551 ac.setClientCluster(clientCluster); 552 ac.setSessionCluster(sessionCluster); 553 ac.setCGIScopeReadonly(cgiReadOnly); 554 if(s3!=null) ac.setS3(AppListenerUtil.toS3(s3)); 555 556 // Scope cascading 557 if(scopeCascading!=-1) ac.setScopeCascading(scopeCascading); 558 559 // ORM 560 boolean initORM=false; 561 if(!update) { 562 if(ormenabled==null)ormenabled=false; 563 if(ormsettings==null)ormsettings=new StructImpl(); 564 } 565 if(ormenabled!=null)ac.setORMEnabled(ormenabled); 566 if(ac.isORMEnabled()) { 567 initORM=true; 568 if(ormsettings!=null)AppListenerUtil.setORMConfiguration(pageContext, ac, ormsettings); 569 } 570 571 572 return initORM; 573 } 574 575 @Override 576 public int doEndTag() { 577 return EVAL_PAGE; 578 } 579 580}