| 1 | <!--- |
|---|
| 2 | Copyright 2006-2007 TeraTech, Inc. http://teratech.com/ |
|---|
| 3 | |
|---|
| 4 | Licensed under the Apache License, Version 2.0 (the "License"); |
|---|
| 5 | you may not use this file except in compliance with the License. |
|---|
| 6 | You may obtain a copy of the License at |
|---|
| 7 | |
|---|
| 8 | http://www.apache.org/licenses/LICENSE-2.0 |
|---|
| 9 | |
|---|
| 10 | Unless required by applicable law or agreed to in writing, software |
|---|
| 11 | distributed under the License is distributed on an "AS IS" BASIS, |
|---|
| 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|---|
| 13 | See the License for the specific language governing permissions and |
|---|
| 14 | limitations under the License. |
|---|
| 15 | ---> |
|---|
| 16 | <cfcomponent output="false" hint="I am the Fusebox application object, formerly the application.fusebox data structure."> |
|---|
| 17 | |
|---|
| 18 | <cfscript> |
|---|
| 19 | // initialize the fusebox (available to be read by developers but not to be written to) |
|---|
| 20 | this.isFullyLoaded = false; |
|---|
| 21 | this.circuits = structNew(); |
|---|
| 22 | this.classes = structNew(); |
|---|
| 23 | this.lexicons = structNew(); |
|---|
| 24 | this.plugins = structNew(); |
|---|
| 25 | this.pluginphases = structNew(); |
|---|
| 26 | this.nonFatalExceptionPrefix = "INFORMATION (can be ignored): "; |
|---|
| 27 | |
|---|
| 28 | // this always has to be overridden: |
|---|
| 29 | this.defaultFuseaction = ""; |
|---|
| 30 | |
|---|
| 31 | this.precedenceFormOrURL = "form"; |
|---|
| 32 | this.fuseactionVariable = "fuseaction"; |
|---|
| 33 | |
|---|
| 34 | // these are all ignored: |
|---|
| 35 | this.parseWithComments = false; |
|---|
| 36 | this.ignoreBadGrammar = true; |
|---|
| 37 | this.allowLexicon = true; |
|---|
| 38 | this.useAssertions = true; |
|---|
| 39 | |
|---|
| 40 | // FB55: this is implemented now: |
|---|
| 41 | this.conditionalParse = false; |
|---|
| 42 | |
|---|
| 43 | this.password = ""; |
|---|
| 44 | this.mode = "production"; |
|---|
| 45 | this.scriptLanguage = "cfmx"; |
|---|
| 46 | this.scriptFileDelimiter = "cfm"; |
|---|
| 47 | this.maskedFileDelimiters = "htm,cfm,cfml,php,php4,asp,aspx"; |
|---|
| 48 | this.characterEncoding = "utf-8"; |
|---|
| 49 | // this is ignored: |
|---|
| 50 | this.parseWithIndentation = this.parseWithComments; |
|---|
| 51 | this.strictMode = false; |
|---|
| 52 | this.allowImplicitFusebox = false; |
|---|
| 53 | this.allowImplicitCircuits = false; |
|---|
| 54 | this.debug = false; |
|---|
| 55 | </cfscript> |
|---|
| 56 | |
|---|
| 57 | <cffunction name="init" returntype="fuseboxApplication" access="public" output="false" |
|---|
| 58 | hint="I am the constructor."> |
|---|
| 59 | <cfargument name="appKey" type="string" required="true" |
|---|
| 60 | hint="I am FUSEBOX_APPLICATION_KEY." /> |
|---|
| 61 | <cfargument name="appPath" type="string" required="true" |
|---|
| 62 | hint="I am FUSEBOX_APPLICATION_PATH." /> |
|---|
| 63 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 64 | hint="I am the myFusebox data structure." /> |
|---|
| 65 | <cfargument name="callerPath" type="string" required="true" |
|---|
| 66 | hint="I am FUSEBOX_CALLER_PATH." /> |
|---|
| 67 | <cfargument name="appParameters" type="struct" required="true" |
|---|
| 68 | hint="I am FUSEBOX_PARAMETERS." /> |
|---|
| 69 | |
|---|
| 70 | <cfset var myVersion = "5.5.0" /> |
|---|
| 71 | <!--- <cfset var myVersion = "5.5.0.#REReplace('$LastChangedRevision$','[^0-9]','','all')#" /> ---> |
|---|
| 72 | |
|---|
| 73 | <cfset variables.factory = createObject("component","fuseboxFactory").init() /> |
|---|
| 74 | <cfset variables.fuseboxLexicon = variables.factory.getBuiltinLexicon() /> |
|---|
| 75 | <cfset variables.customAttributes = structNew() /> |
|---|
| 76 | |
|---|
| 77 | <cfset variables.fuseboxFileExtension = "" /> |
|---|
| 78 | |
|---|
| 79 | <cfset variables.fuseboxVersion = myVersion /> |
|---|
| 80 | |
|---|
| 81 | <cfset variables.appKey = arguments.appKey /> |
|---|
| 82 | <cfset this.webrootdirectory = replace(getDirectoryFromPath(getBaseTemplatePath()),"\","/","all") /> |
|---|
| 83 | <cfset variables.coreRoot = replace(getDirectoryFromPath(getCurrentTemplatePath()),"\","/","all") /> |
|---|
| 84 | |
|---|
| 85 | <cfset this.approotdirectory = getCanonicalPath(normalizePartialPath(arguments.callerPath) & normalizePartialPath(arguments.appPath)) /> |
|---|
| 86 | |
|---|
| 87 | <!--- this works on all platforms: ---> |
|---|
| 88 | <cfset this.osdelimiter = "/" /> |
|---|
| 89 | |
|---|
| 90 | <cfset this.coreToAppRootPath = relativePath(variables.coreRoot,this.approotdirectory) /> |
|---|
| 91 | <cfset this.appRootPathToCore = relativePath(this.approotdirectory,variables.coreRoot) /> |
|---|
| 92 | <cfset this.coreToWebRootPath = relativePath(variables.coreRoot,this.webrootdirectory) /> |
|---|
| 93 | <cfset this.WebRootPathToCore = relativePath(this.webrootdirectory,variables.coreRoot) /> |
|---|
| 94 | |
|---|
| 95 | <cfset this.parsePath = "parsed/" /> |
|---|
| 96 | <cfset this.parseRootPath = "../" /> |
|---|
| 97 | <cfset this.pluginsPath = "plugins/" /> |
|---|
| 98 | <cfset this.lexiconPath = "lexicon/" /> |
|---|
| 99 | <cfset this.errortemplatesPath = "errortemplates/" /> |
|---|
| 100 | |
|---|
| 101 | <!--- new in Fusebox 5.1: ---> |
|---|
| 102 | <cfset this.self = CGI.SCRIPT_NAME /> |
|---|
| 103 | <cfset this.queryStringStart = "?" /> |
|---|
| 104 | <cfset this.queryStringSeparator = "&" /> |
|---|
| 105 | <cfset this.queryStringEqual = "=" /> |
|---|
| 106 | |
|---|
| 107 | <cfset this.circuits = structNew() /> |
|---|
| 108 | <cfset reload(arguments.appKey,arguments.appPath,arguments.myFusebox,arguments.appParameters) /> |
|---|
| 109 | |
|---|
| 110 | <cfif this.strictMode> |
|---|
| 111 | <!--- rootdirectory was deprecated in Fusebox 5 so we no longer set it it strict mode: ---> |
|---|
| 112 | <cfset structDelete(this,"rootdirectory") /> |
|---|
| 113 | <cfelse> |
|---|
| 114 | <!--- for FB4.0 compatibility: ---> |
|---|
| 115 | <cfset this.rootdirectory = this.approotdirectory /> |
|---|
| 116 | </cfif> |
|---|
| 117 | |
|---|
| 118 | <cfreturn this /> |
|---|
| 119 | |
|---|
| 120 | </cffunction> |
|---|
| 121 | |
|---|
| 122 | <cffunction name="reload" returntype="void" access="public" output="false" |
|---|
| 123 | hint="I (re)load the fusebox.xml file into memory and (re)load all of the application components referenced by that."> |
|---|
| 124 | <cfargument name="appKey" type="string" required="true" |
|---|
| 125 | hint="I am FUSEBOX_APPLICATION_KEY." /> |
|---|
| 126 | <cfargument name="appPath" type="string" required="true" |
|---|
| 127 | hint="I am FUSEBOX_APPLICATION_PATH." /> |
|---|
| 128 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 129 | hint="I am the myFusebox data structure." /> |
|---|
| 130 | <cfargument name="appParameters" type="struct" required="true" |
|---|
| 131 | hint="I am FUSEBOX_PARAMETERS." /> |
|---|
| 132 | |
|---|
| 133 | <cfset var fbFile = "fusebox.xml.cfm" /> |
|---|
| 134 | <cfset var fbFileAlt = "fusebox.xml" /> |
|---|
| 135 | <cfset var fbFileExists = false /> |
|---|
| 136 | <cfset var fbXML = "" /> |
|---|
| 137 | <cfset var fbCode = "" /> |
|---|
| 138 | <cfset var encodings = 0 /> |
|---|
| 139 | <cfset var needToLoad = true /> |
|---|
| 140 | <cfset var fuseboxFiles = 0 /> |
|---|
| 141 | <cfset var p = "" /> |
|---|
| 142 | |
|---|
| 143 | <!--- FB55: cache of parsed file signatures ---> |
|---|
| 144 | <cfset variables.parsedFileCache = structNew() /> |
|---|
| 145 | |
|---|
| 146 | <!--- FB55: can override fusebox.xml parameters programmatically ---> |
|---|
| 147 | <!--- this sets up the defaults for the reload - prior to actually reading parameters ---> |
|---|
| 148 | <cfloop collection="#arguments.appParameters#" item="p"> |
|---|
| 149 | <cfset this[p] = arguments.appParameters[p] /> |
|---|
| 150 | </cfloop> |
|---|
| 151 | <cfif structKeyExists(this,"allowImplicitFusebox") and this.allowImplicitFusebox> |
|---|
| 152 | <cfset this.allowImplicitCircuits = true /> |
|---|
| 153 | </cfif> |
|---|
| 154 | |
|---|
| 155 | <!--- |
|---|
| 156 | since we need to check the file, regardless of whether we load it, |
|---|
| 157 | we might as well do the test up front and perform the strict check |
|---|
| 158 | that just one version exists (ticket 135) |
|---|
| 159 | ---> |
|---|
| 160 | <cfset fbFileExists = fileExists(this.approotdirectory & fbFile) /> |
|---|
| 161 | <cfif fbFileExists> |
|---|
| 162 | <cfif this.strictMode and fileExists(this.approotdirectory & fbFileAlt)> |
|---|
| 163 | <cfthrow type="fusebox.multipleFuseboxXML" |
|---|
| 164 | message="Both 'fusebox.xml' and 'fusebox.xml.cfm' exist" |
|---|
| 165 | detail="'fusebox.xml.cfm' will be used but 'fusebox.xml' also exists in '#this.approotdirectory#." /> |
|---|
| 166 | </cfif> |
|---|
| 167 | <cfelse> |
|---|
| 168 | <cfset fbFile = fbFileAlt /> |
|---|
| 169 | <cfset fbFileExists = fileExists(this.approotdirectory & fbFile) /> |
|---|
| 170 | </cfif> |
|---|
| 171 | |
|---|
| 172 | <cfif structKeyExists(this,"timestamp")> |
|---|
| 173 | <cfif fbFileExists> |
|---|
| 174 | <!--- we only check the time stamp if the file exists ---> |
|---|
| 175 | <cfset needToLoad = fileModificationDate(this.approotdirectory & fbFile) gt parseDateTime(this.timestamp) /> |
|---|
| 176 | <cfelse> |
|---|
| 177 | <!--- |
|---|
| 178 | if we loaded the application and there is no fusebox.xml file, |
|---|
| 179 | then we must have loaded an implicit fusebox.xml file so there |
|---|
| 180 | is no need to reload it again because an implicit file can't change! |
|---|
| 181 | ---> |
|---|
| 182 | <cfset needToLoad = false /> |
|---|
| 183 | </cfif> |
|---|
| 184 | </cfif> |
|---|
| 185 | |
|---|
| 186 | <cfif needToLoad> |
|---|
| 187 | |
|---|
| 188 | <cfif this.debug> |
|---|
| 189 | <cfset arguments.myFusebox.trace("Compiler","Loading fusebox.xml file") /> |
|---|
| 190 | </cfif> |
|---|
| 191 | |
|---|
| 192 | <!--- attempt to load fusebox.xml(.cfm): ---> |
|---|
| 193 | <cfif fbFileExists> |
|---|
| 194 | <cftry> |
|---|
| 195 | |
|---|
| 196 | <cffile action="read" file="#this.approotdirectory##fbFile#" |
|---|
| 197 | variable="fbXML" |
|---|
| 198 | charset="#this.characterEncoding#" /> |
|---|
| 199 | |
|---|
| 200 | <cfset variables.fuseboxFileExtension = listLast(fbFile,".") /> |
|---|
| 201 | |
|---|
| 202 | <cfcatch type="security"> |
|---|
| 203 | <!--- cffile denied by sandbox security ---> |
|---|
| 204 | <cfthrow type="fusebox.security" |
|---|
| 205 | message="security error reading fusebox.xml" |
|---|
| 206 | detail="The file '#fbFile#' in the directory #this.approotdirectory# could not be read because sandbox security has disabled the cffile tag." |
|---|
| 207 | extendedinfo="#cfcatch.detail#" /> |
|---|
| 208 | </cfcatch> |
|---|
| 209 | |
|---|
| 210 | <cfcatch type="any"> |
|---|
| 211 | <!--- the file exists but we cannot read it ---> |
|---|
| 212 | <cfthrow type="fusebox.missingFuseboxXML" |
|---|
| 213 | message="missing fusebox.xml" |
|---|
| 214 | detail="The file '#fbFile#' in the directory #this.approotdirectory# could not be read." |
|---|
| 215 | extendedinfo="#cfcatch.detail#" /> |
|---|
| 216 | </cfcatch> |
|---|
| 217 | |
|---|
| 218 | </cftry> |
|---|
| 219 | |
|---|
| 220 | <cfelse> |
|---|
| 221 | |
|---|
| 222 | <cfif this.allowImplicitFusebox> |
|---|
| 223 | |
|---|
| 224 | <cfif this.debug> |
|---|
| 225 | <cfset arguments.myFusebox.trace("Compiler","Implicit fusebox.xml(.cfm) identified") /> |
|---|
| 226 | </cfif> |
|---|
| 227 | <cfset fbXML = "<fusebox/>" /> |
|---|
| 228 | <!--- if the fusebox.xml file is missing there are no circuit declarations: ---> |
|---|
| 229 | <cfset this.allowImplicitCircuits = true /> |
|---|
| 230 | |
|---|
| 231 | <cfelse> |
|---|
| 232 | |
|---|
| 233 | <cfthrow type="fusebox.missingFuseboxXML" |
|---|
| 234 | message="missing fusebox.xml" |
|---|
| 235 | detail="The file '#fbFile#' could not be found in the directory #this.approotdirectory#." /> |
|---|
| 236 | |
|---|
| 237 | </cfif> |
|---|
| 238 | |
|---|
| 239 | </cfif> |
|---|
| 240 | |
|---|
| 241 | <cftry> |
|---|
| 242 | |
|---|
| 243 | <cfset fbCode = xmlParse(fbXML) /> |
|---|
| 244 | |
|---|
| 245 | <!--- see if we need to re-read based on the encoding being different to our default ---> |
|---|
| 246 | <cfset encodings = xmlSearch(fbCode,"/fusebox/parameters/parameter[@name='characterEncoding']") /> |
|---|
| 247 | <cfif arrayLen(encodings) eq 1 and structKeyExists(encodings[1].xmlAttributes,"value")> |
|---|
| 248 | <cfif encodings[1].xmlAttributes.value is not this.characterEncoding> |
|---|
| 249 | <cfset this.characterEncoding = encodings[1].xmlAttributes.value /> |
|---|
| 250 | <!--- now re-read the file in case anything is changed in that new encoding ---> |
|---|
| 251 | <cffile action="read" file="#this.approotdirectory##fbFile#" |
|---|
| 252 | variable="fbXML" |
|---|
| 253 | charset="#this.characterEncoding#" /> |
|---|
| 254 | <cfset fbCode = xmlParse(fbXML) /> |
|---|
| 255 | </cfif> |
|---|
| 256 | </cfif> |
|---|
| 257 | |
|---|
| 258 | <cfcatch type="any"> |
|---|
| 259 | <cfthrow type="fusebox.fuseboxXMLError" |
|---|
| 260 | message="Error reading fusebox.xml" |
|---|
| 261 | detail="A problem was encountered while reading the #fbFile# file. This is usually caused by unmatched XML tags (a <tag> without a </tag> or without use of the <tag/> short-cut.)" |
|---|
| 262 | extendedinfo="#cfcatch.detail#" /> |
|---|
| 263 | </cfcatch> |
|---|
| 264 | |
|---|
| 265 | </cftry> |
|---|
| 266 | |
|---|
| 267 | <cfif fbCode.xmlRoot.xmlName is not "fusebox"> |
|---|
| 268 | <cfthrow type="fusebox.badGrammar.badFuseboxFile" |
|---|
| 269 | detail="Fusebox file does contain 'fusebox' XML" |
|---|
| 270 | message="Fusebox file #fbFile# does not contain 'fusebox' as the root XML node." /> |
|---|
| 271 | </cfif> |
|---|
| 272 | |
|---|
| 273 | <cfset loadParameters(fbCode) /> |
|---|
| 274 | |
|---|
| 275 | <!--- FB55: can override fusebox.xml parameters programmatically ---> |
|---|
| 276 | <cfloop collection="#arguments.appParameters#" item="p"> |
|---|
| 277 | <cfset this[p] = arguments.appParameters[p] /> |
|---|
| 278 | </cfloop> |
|---|
| 279 | <cfif structKeyExists(this,"allowImplicitFusebox") and this.allowImplicitFusebox> |
|---|
| 280 | <cfset this.allowImplicitCircuits = true /> |
|---|
| 281 | </cfif> |
|---|
| 282 | |
|---|
| 283 | <!--- |
|---|
| 284 | if the user overrides certain path variables, we need to normalize them: |
|---|
| 285 | - this.parsePath (reset parseRootPath) |
|---|
| 286 | - this.pluginsPath |
|---|
| 287 | - this.lexiconPath |
|---|
| 288 | - this.errortemplatesPath |
|---|
| 289 | normalizing means changing all \ to / and appending / if not present |
|---|
| 290 | ---> |
|---|
| 291 | <cfset this.parsePath = normalizePartialPath(this.parsePath) /> |
|---|
| 292 | <cfset this.parseRootPath = relativePath(expandFuseboxPath(this.parsePath),getApplicationRoot()) /> |
|---|
| 293 | <cfset this.pluginsPath = normalizePartialPath(this.pluginsPath) /> |
|---|
| 294 | <cfset this.lexiconPath = normalizePartialPath(this.lexiconPath) /> |
|---|
| 295 | <cfset this.errortemplatesPath = normalizePartialPath(this.errortemplatesPath) /> |
|---|
| 296 | |
|---|
| 297 | <!--- Fusebox 5.1: default this.myself: ---> |
|---|
| 298 | <cfif not structKeyExists(this,"myself")> |
|---|
| 299 | <cfset this.myself = getDefaultMyself(this.self) /> |
|---|
| 300 | </cfif> |
|---|
| 301 | |
|---|
| 302 | <cfset loadLexicons(fbCode) /> |
|---|
| 303 | <cfset loadClasses(fbCode) /> |
|---|
| 304 | <cfset loadPlugins(fbCode) /> |
|---|
| 305 | <cfset loadGlobalPreAndPostProcess(fbCode) /> |
|---|
| 306 | <!--- save fusebox.xml DOM internally for (re-)loading circuits ---> |
|---|
| 307 | <cfset variables.fbCode = fbCode /> |
|---|
| 308 | <cfset variables.fbFile = fbFile /> |
|---|
| 309 | <cfset this.timestamp = now() /> |
|---|
| 310 | </cfif> |
|---|
| 311 | |
|---|
| 312 | <!--- to track circuit loads on this request ---> |
|---|
| 313 | <cfparam name="request.__fusebox.CircuitsLoaded" default="#structNew()#" /> |
|---|
| 314 | <cfset loadCircuits(variables.fbCode,arguments.myFusebox) /> |
|---|
| 315 | |
|---|
| 316 | <!--- FB5: fusebox.loadclean will delete all the parsed files ---> |
|---|
| 317 | <cfif arguments.myFusebox.parameters.clean> |
|---|
| 318 | <cfset deleteParsedFiles() /> |
|---|
| 319 | </cfif> |
|---|
| 320 | |
|---|
| 321 | <!--- application data available to developers via getApplicationData() method: ---> |
|---|
| 322 | <cfset variables.data = structNew() /> |
|---|
| 323 | |
|---|
| 324 | <cfset this.isFullyLoaded = true /> |
|---|
| 325 | <cfset this.applicationStarted = false /> |
|---|
| 326 | <cfset this.dateLastLoaded = now() /> |
|---|
| 327 | |
|---|
| 328 | <!--- |
|---|
| 329 | The following documented parts of application.fusebox are not supported in Fusebox 5: |
|---|
| 330 | - application.fusebox.xml |
|---|
| 331 | - application.fusebox.globalfuseactions.* |
|---|
| 332 | - application.fusebox.circuits.*.xml |
|---|
| 333 | - application.fusebox.circuits.preFuseaction.* |
|---|
| 334 | - application.fusebox.circuits.postFuseaction.* |
|---|
| 335 | - application.fusebox.circuits.*.fuseactions.*.xml |
|---|
| 336 | ---> |
|---|
| 337 | |
|---|
| 338 | </cffunction> |
|---|
| 339 | |
|---|
| 340 | <cffunction name="getPluginsPath" returntype="string" access="public" output="false" |
|---|
| 341 | hint="I am a convenience method to return the location of the plugins."> |
|---|
| 342 | |
|---|
| 343 | <cfreturn this.pluginsPath /> |
|---|
| 344 | |
|---|
| 345 | </cffunction> |
|---|
| 346 | |
|---|
| 347 | <!--- FB55: exposes this directly in myFusebox for convenience ---> |
|---|
| 348 | <cffunction name="getApplicationData" returntype="struct" access="public" output="false" |
|---|
| 349 | hint="I return a reference to the application data cache. This is a new concept in Fusebox 5."> |
|---|
| 350 | |
|---|
| 351 | <cfreturn variables.data /> |
|---|
| 352 | |
|---|
| 353 | </cffunction> |
|---|
| 354 | |
|---|
| 355 | <cffunction name="getApplicationRoot" returntype="any" access="public" output="false" |
|---|
| 356 | hint="I am a convenience method to return the full application root directory path."> |
|---|
| 357 | |
|---|
| 358 | <cfreturn this.approotdirectory /> |
|---|
| 359 | |
|---|
| 360 | </cffunction> |
|---|
| 361 | |
|---|
| 362 | <cffunction name="expandFuseboxPath" returntype="any" access="public" output="false" |
|---|
| 363 | hint="I expand a path in the context of a Fusebox application."> |
|---|
| 364 | <cfargument name="partialPath" type="any" required="true" |
|---|
| 365 | hint="I am the partial path to expand. If I do not begin with a /, prepend the Fusebox application root." /> |
|---|
| 366 | |
|---|
| 367 | <cfif left(arguments.partialPath,1) is "/"> |
|---|
| 368 | <!--- absolute path, i.e., root-relative or mapped ---> |
|---|
| 369 | <cfreturn replace(expandPath(arguments.partialPath),"\","/","all") /> |
|---|
| 370 | <cfelse> |
|---|
| 371 | <!--- relative, i.e., relative to the Fusebox application root ---> |
|---|
| 372 | <cfreturn getApplicationRoot() & arguments.partialPath /> |
|---|
| 373 | </cfif> |
|---|
| 374 | |
|---|
| 375 | </cffunction> |
|---|
| 376 | |
|---|
| 377 | <cffunction name="getFuseboxXMLFilename" returntype="string" access="public" output="false" |
|---|
| 378 | hint="I return the actual name of the fusebox.xml(.cfm) file."> |
|---|
| 379 | |
|---|
| 380 | <cfreturn variables.fbFile /> |
|---|
| 381 | |
|---|
| 382 | </cffunction> |
|---|
| 383 | |
|---|
| 384 | <cffunction name="getCoreToAppRootPath" returntype="any" access="public" output="false" |
|---|
| 385 | hint="I am a convenience method to return the relative path from the core files to the application root."> |
|---|
| 386 | |
|---|
| 387 | <cfreturn this.coreToAppRootPath /> |
|---|
| 388 | |
|---|
| 389 | </cffunction> |
|---|
| 390 | |
|---|
| 391 | <cffunction name="compileAll" returntype="void" access="public" output="false" |
|---|
| 392 | hint="I compile all the public fuseactions in the application."> |
|---|
| 393 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 394 | hint="I am the myFusebox data structure." /> |
|---|
| 395 | |
|---|
| 396 | <cfset var c = 0 /> |
|---|
| 397 | <cfset var a = 0 /> |
|---|
| 398 | <cfset var f = 0 /> |
|---|
| 399 | |
|---|
| 400 | <cfloop collection="#this.circuits#" item="c"> |
|---|
| 401 | <cfset a = this.circuits[c].getFuseactions() /> |
|---|
| 402 | <cfloop collection="#a#" item="f"> |
|---|
| 403 | <cfif a[f].access is "public"> |
|---|
| 404 | <cfset compileRequest(c & "." & f,arguments.myFusebox) /> |
|---|
| 405 | </cfif> |
|---|
| 406 | </cfloop> |
|---|
| 407 | </cfloop> |
|---|
| 408 | |
|---|
| 409 | </cffunction> |
|---|
| 410 | |
|---|
| 411 | <cffunction name="compileRequest" returntype="struct" access="public" output="false" |
|---|
| 412 | hint="I compile a specific (public) fuseaction as an external request."> |
|---|
| 413 | <cfargument name="circuitFuseaction" type="string" required="true" |
|---|
| 414 | hint="I am the full name of the requested fuseaction (circuit.fuseaction)." /> |
|---|
| 415 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 416 | hint="I am the myFusebox data structure." /> |
|---|
| 417 | |
|---|
| 418 | <cfset var myVersion = getVersion() /> |
|---|
| 419 | <cfset var circuit = "" /> |
|---|
| 420 | <cfset var fuseaction = listLast(arguments.circuitFuseaction,".") /> |
|---|
| 421 | <cfset var i = 0 /> |
|---|
| 422 | <cfset var n = 0 /> |
|---|
| 423 | <cfset var needRethrow = true /> |
|---|
| 424 | <cfset var needTryOnFuseaction = false /> |
|---|
| 425 | <cfset var parsedName = "#lCase(arguments.circuitFuseaction)#.cfm" /> |
|---|
| 426 | <cfset var parsedFile = "#this.parsePath##parsedName#" /> |
|---|
| 427 | <cfset var fullParsedFile = "#this.expandFuseboxPath(this.parsePath)##parsedName#" /> |
|---|
| 428 | <cfset var result = structNew() /> |
|---|
| 429 | <cfset var writer = 0 /> |
|---|
| 430 | |
|---|
| 431 | <!--- to track reloads on this request ---> |
|---|
| 432 | <cfparam name="request.__fusebox.CircuitsLoaded" default="#structNew()#" /> |
|---|
| 433 | <cfparam name="request.__fusebox.fuseactionsDone" default="#structNew()#" /> |
|---|
| 434 | |
|---|
| 435 | <!--- note that in Fusebox 5, these are really all the same set of files ---> |
|---|
| 436 | <cfset arguments.myFusebox.version.loader = myVersion /> |
|---|
| 437 | <cfset arguments.myFusebox.version.parser = myVersion /> |
|---|
| 438 | <cfset arguments.myFusebox.version.transformer = myVersion /> |
|---|
| 439 | <!--- legacy test from FB41 although it's a bit pointless ---> |
|---|
| 440 | <cfif myFusebox.version.runtime neq myFusebox.version.loader> |
|---|
| 441 | <cfthrow type="fusebox.versionMismatchException" |
|---|
| 442 | message="The loader is not the same version as the runtime" /> |
|---|
| 443 | </cfif> |
|---|
| 444 | |
|---|
| 445 | <!--- validate format of the fuseaction: ---> |
|---|
| 446 | <cfif listLen(arguments.circuitFuseaction,".") lt 2> |
|---|
| 447 | <cfthrow type="fusebox.malformedFuseaction" |
|---|
| 448 | message="malformed Fuseaction" |
|---|
| 449 | detail="You specified a malformed Fuseaction of #arguments.circuitFuseaction#. A fully qualified Fuseaction must be in the form [Circuit].[Fuseaction]." /> |
|---|
| 450 | </cfif> |
|---|
| 451 | |
|---|
| 452 | <cfset circuit = left(arguments.circuitFuseaction,len(arguments.circuitFuseaction)-len(fuseaction)-1) /> |
|---|
| 453 | |
|---|
| 454 | <!--- set up myFusebox values for this request: ---> |
|---|
| 455 | <cfset arguments.myFusebox.originalCircuit = circuit /> |
|---|
| 456 | <cfset arguments.myFusebox.originalFuseaction = fuseaction /> |
|---|
| 457 | <cfloop collection="#this.plugins#" item="i"> |
|---|
| 458 | <cfset arguments.myFusebox.plugins[i] = structNew() /> |
|---|
| 459 | </cfloop> |
|---|
| 460 | |
|---|
| 461 | <!--- ticket 293 - prevent dynamic do() from executing until prerequisites complete ---> |
|---|
| 462 | <cfset request.__fusebox.dynamicDoOK = true /> |
|---|
| 463 | |
|---|
| 464 | <!--- check access on request - if the circuit/fuseaction doesn't exist we trap it later ---> |
|---|
| 465 | <cfif structKeyExists(this.circuits,circuit) and |
|---|
| 466 | structKeyExists(this.circuits[circuit].fuseactions,fuseaction) and |
|---|
| 467 | this.circuits[circuit].fuseactions[fuseaction].getAccess() is not "public"> |
|---|
| 468 | <cfthrow type="fusebox.invalidAccessModifier" |
|---|
| 469 | message="Invalid Access Modifier" |
|---|
| 470 | detail="You tried to access #circuit#.#fuseaction# which does not have access modifier of public. A Fuseaction which is to be accessed from anywhere outside the application (such as called via an URL, or a FORM, or as a web service) must have an access modifier of public or if unspecified at least inherit such a modifier from its circuit."> |
|---|
| 471 | </cfif> |
|---|
| 472 | |
|---|
| 473 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 474 | <cflock name="#fullParsedFile#" type="exclusive" timeout="300"> |
|---|
| 475 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 476 | <cfset request.__fusebox.SuppressPlugins = false /> |
|---|
| 477 | <cfset writer = createObject("component","fuseboxWriter").init(this,arguments.myFusebox) /> |
|---|
| 478 | <cfset writer.open(parsedName) /> |
|---|
| 479 | <cfset writer.rawPrintln("<!--- circuit: #circuit# --->") /> |
|---|
| 480 | <cfset writer.rawPrintln("<!--- fuseaction: #fuseaction# --->") /> |
|---|
| 481 | <cfset writer.rawPrintln("<cftry>") /> |
|---|
| 482 | <cfset writer.setCircuit(circuit) /> |
|---|
| 483 | <cfset writer.setFuseaction(fuseaction) /> |
|---|
| 484 | <cfif variables.hasProcess["appinit"]> |
|---|
| 485 | <cfset writer.setPhase("appinit") /> |
|---|
| 486 | <cfset writer.println("<cfif myFusebox.applicationStart or") /> |
|---|
| 487 | <cfset writer.println(' not myFusebox.getApplication().applicationStarted>') /> |
|---|
| 488 | <cfset writer.println(' <cflock name="##application.ApplicationName##_fusebox_##FUSEBOX_APPLICATION_KEY##_appinit" type="exclusive" timeout="30">') /> |
|---|
| 489 | <cfset writer.println(' <cfif not myFusebox.getApplication().applicationStarted>') /> |
|---|
| 490 | <cfset request.__fusebox.SuppressPlugins = true /> |
|---|
| 491 | <cfset variables.process["appinit"].compile(writer) /> |
|---|
| 492 | <cfset writer.println(' <cfset myFusebox.getApplication().applicationStarted = true />') /> |
|---|
| 493 | <cfset writer.println(' </cfif>') /> |
|---|
| 494 | <cfset writer.println(' </cflock>') /> |
|---|
| 495 | <cfset writer.println('</cfif>') /> |
|---|
| 496 | </cfif> |
|---|
| 497 | <cfset request.__fusebox.SuppressPlugins = false /> |
|---|
| 498 | <cfif structKeyExists(this.pluginPhases,"preProcess")> |
|---|
| 499 | <cfset n = arrayLen(this.pluginPhases["preProcess"]) /> |
|---|
| 500 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 501 | <cfset this.pluginPhases["preProcess"][i].compile(writer) /> |
|---|
| 502 | </cfloop> |
|---|
| 503 | </cfif> |
|---|
| 504 | <cfset writer.setPhase("preprocessFuseactions") /> |
|---|
| 505 | <cfif variables.hasProcess["preprocess"]> |
|---|
| 506 | <cfset variables.process["preprocess"].compile(writer) /> |
|---|
| 507 | </cfif> |
|---|
| 508 | <cfif structKeyExists(this.pluginPhases,"fuseactionException") and |
|---|
| 509 | arrayLen(this.pluginPhases["fuseactionException"]) gt 0 and |
|---|
| 510 | not request.__fusebox.SuppressPlugins> |
|---|
| 511 | <cfset needTryOnFuseaction = true /> |
|---|
| 512 | <cfset writer.rawPrintln("<cftry>") /> |
|---|
| 513 | </cfif> |
|---|
| 514 | <cfif structKeyExists(this.pluginPhases,"preFuseaction")> |
|---|
| 515 | <cfset n = arrayLen(this.pluginPhases["preFuseaction"]) /> |
|---|
| 516 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 517 | <cfset this.pluginPhases["preFuseaction"][i].compile(writer) /> |
|---|
| 518 | </cfloop> |
|---|
| 519 | </cfif> |
|---|
| 520 | <cfset writer.setPhase("requestedFuseaction") /> |
|---|
| 521 | <cfset compile(writer,circuit,fuseaction,true) /> |
|---|
| 522 | <cfif structKeyExists(this.pluginPhases,"postFuseaction")> |
|---|
| 523 | <cfset n = arrayLen(this.pluginPhases["postFuseaction"]) /> |
|---|
| 524 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 525 | <cfset this.pluginPhases["postFuseaction"][i].compile(writer) /> |
|---|
| 526 | </cfloop> |
|---|
| 527 | </cfif> |
|---|
| 528 | <cfif needTryOnFuseaction> |
|---|
| 529 | <cfset n = arrayLen(this.pluginPhases["fuseactionException"]) /> |
|---|
| 530 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 531 | <cfset this.pluginPhases["fuseactionException"][i].compile(writer) /> |
|---|
| 532 | </cfloop> |
|---|
| 533 | <cfset writer.rawPrintln("</cftry>") /> |
|---|
| 534 | </cfif> |
|---|
| 535 | <cfset writer.setPhase("postprocessFuseactions") /> |
|---|
| 536 | <cfif variables.hasProcess["postprocess"]> |
|---|
| 537 | <cfset variables.process["postprocess"].compile(writer) /> |
|---|
| 538 | </cfif> |
|---|
| 539 | <cfif structKeyExists(this.pluginPhases,"postProcess")> |
|---|
| 540 | <cfset n = arrayLen(this.pluginPhases["postProcess"]) /> |
|---|
| 541 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 542 | <cfset this.pluginPhases["postProcess"][i].compile(writer) /> |
|---|
| 543 | </cfloop> |
|---|
| 544 | </cfif> |
|---|
| 545 | <cfif structKeyExists(this.pluginPhases,"processError") and |
|---|
| 546 | not request.__fusebox.SuppressPlugins> |
|---|
| 547 | <cfset n = arrayLen(this.pluginPhases["processError"]) /> |
|---|
| 548 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 549 | <cfset needRethrow = false /> |
|---|
| 550 | <cfset this.pluginPhases["processError"][i].compile(writer) /> |
|---|
| 551 | </cfloop> |
|---|
| 552 | </cfif> |
|---|
| 553 | <cfif needRethrow> |
|---|
| 554 | <cfset writer.rawPrintln('<' & 'cfcatch><' & 'cfrethrow><' & '/cfcatch>') /> |
|---|
| 555 | </cfif> |
|---|
| 556 | <cfset writer.rawPrintln("</cftry>") /> |
|---|
| 557 | <cfset writer.close(variables.parsedFileCache) /> |
|---|
| 558 | </cfif> |
|---|
| 559 | </cflock> |
|---|
| 560 | </cfif> |
|---|
| 561 | |
|---|
| 562 | <cfset result.parsedName = parsedName /> |
|---|
| 563 | <cfif left(parsedFile,1) is "/"> |
|---|
| 564 | <cfset result.parsedFile = parsedFile /> |
|---|
| 565 | <cfelse> |
|---|
| 566 | <cfset result.parsedFile = this.getCoreToAppRootPath() & parsedFile /> |
|---|
| 567 | </cfif> |
|---|
| 568 | <cfset result.lockName = fullParsedFile /> |
|---|
| 569 | |
|---|
| 570 | <cfreturn result /> |
|---|
| 571 | |
|---|
| 572 | </cffunction> |
|---|
| 573 | |
|---|
| 574 | <cffunction name="do" returntype="string" access="public" output="true" |
|---|
| 575 | hint="I compile and execute a specific fuseaction."> |
|---|
| 576 | <cfargument name="circuitFuseaction" type="string" required="true" |
|---|
| 577 | hint="I am the full name of the requested fuseaction (circuit.fuseaction)." /> |
|---|
| 578 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 579 | hint="I am the myFusebox data structure." /> |
|---|
| 580 | <cfargument name="returnOutput" type="boolean" required="true" |
|---|
| 581 | hint="I indicate whether to display output (false) or return the output (true)." /> |
|---|
| 582 | |
|---|
| 583 | <cfset var parsedFileInfo = 0 /> |
|---|
| 584 | <cfset var output = "" /> |
|---|
| 585 | |
|---|
| 586 | <!--- ticket 293 - prevent dynamic do() from executing until prerequisites complete ---> |
|---|
| 587 | <cfif not structKeyExists(request,"__fusebox") or |
|---|
| 588 | not structKeyExists(request.__fusebox,"dynamicDoOK") or |
|---|
| 589 | not request.__fusebox.dynamicDoOK> |
|---|
| 590 | <cfif structKeyExists(arguments.myFusebox,"originalCircuit") and |
|---|
| 591 | structKeyExists(arguments.myFusebox,"originalFuseaction")> |
|---|
| 592 | <cfset output = output & " while executing " & arguments.myFusebox.originalCircuit & |
|---|
| 593 | "." & arguments.myFusebox.originalFuseaction /> |
|---|
| 594 | </cfif> |
|---|
| 595 | <cfthrow type="fusebox.dynamicDoNotAllowed" message="dynamic 'do' not allowed" |
|---|
| 596 | detail="This request did not reach the state where dynamic 'do' is possible#output#." /> |
|---|
| 597 | </cfif> |
|---|
| 598 | |
|---|
| 599 | <!--- allow for abbreviated circuitFuseaction form: ---> |
|---|
| 600 | <cfif listLen(arguments.circuitFuseaction,".") lt 2> |
|---|
| 601 | <cfset arguments.circuitFuseaction = arguments.myFusebox.thisCircuit & "." & arguments.circuitFuseaction /> |
|---|
| 602 | </cfif> |
|---|
| 603 | <!--- TODO: check for accessibility ---> |
|---|
| 604 | |
|---|
| 605 | <cfset parsedFileInfo = compileDynamicDo(arguments.circuitFuseaction,arguments.myFusebox) /> |
|---|
| 606 | |
|---|
| 607 | <cfif this.debug> |
|---|
| 608 | <cfset arguments.myFusebox.trace("Runtime","<do action=""#arguments.circuitFuseaction#""/> -- dynamic") /> |
|---|
| 609 | </cfif> |
|---|
| 610 | <cfinvoke component="fuseboxExecutionContext" method="__executeDynamicDo" returnvariable="output" |
|---|
| 611 | parsedFileInfo="#parsedFileInfo#" myFusebox="#arguments.myFusebox#" returnOutput="#arguments.returnOutput#" /> |
|---|
| 612 | |
|---|
| 613 | <cfreturn output /> |
|---|
| 614 | |
|---|
| 615 | </cffunction> |
|---|
| 616 | |
|---|
| 617 | <cffunction name="compileDynamicDo" returntype="struct" access="private" output="false" |
|---|
| 618 | hint="I compile a specific fuseaction as a dynamic request."> |
|---|
| 619 | <cfargument name="circuitFuseaction" type="string" required="true" |
|---|
| 620 | hint="I am the full name of the requested fuseaction (circuit.fuseaction)." /> |
|---|
| 621 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 622 | hint="I am the myFusebox data structure." /> |
|---|
| 623 | |
|---|
| 624 | <cfset var circuit = "" /> |
|---|
| 625 | <cfset var fuseaction = listLast(arguments.circuitFuseaction,".") /> |
|---|
| 626 | <cfset var i = 0 /> |
|---|
| 627 | <cfset var n = 0 /> |
|---|
| 628 | <cfset var needTryOnFuseaction = false /> |
|---|
| 629 | <cfset var parsedName = "do.#lCase(arguments.circuitFuseaction)#.cfm" /> |
|---|
| 630 | <cfset var parsedFile = "#this.parsePath##parsedName#" /> |
|---|
| 631 | <cfset var fullParsedFile = "#this.expandFuseboxPath(this.parsePath)##parsedName#" /> |
|---|
| 632 | <cfset var result = structNew() /> |
|---|
| 633 | <cfset var writer = 0 /> |
|---|
| 634 | |
|---|
| 635 | <!--- validate format of the fuseaction: ---> |
|---|
| 636 | <cfif listLen(arguments.circuitFuseaction,".") lt 2> |
|---|
| 637 | <cfthrow type="fusebox.malformedFuseaction" |
|---|
| 638 | message="malformed Fuseaction" |
|---|
| 639 | detail="You specified a malformed Fuseaction of #arguments.circuitFuseaction#. A fully qualified Fuseaction must be in the form [Circuit].[Fuseaction]." /> |
|---|
| 640 | </cfif> |
|---|
| 641 | |
|---|
| 642 | <cfset circuit = left(arguments.circuitFuseaction,len(arguments.circuitFuseaction)-len(fuseaction)-1) /> |
|---|
| 643 | |
|---|
| 644 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 645 | <cflock name="#fullParsedFile#" type="exclusive" timeout="300"> |
|---|
| 646 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 647 | <cfset writer = createObject("component","fuseboxWriter").init(this,arguments.myFusebox) /> |
|---|
| 648 | <cfset writer.open(parsedName) /> |
|---|
| 649 | <cfset writer.rawPrintln("<!--- circuit: #circuit# --->") /> |
|---|
| 650 | <cfset writer.rawPrintln("<!--- fuseaction: #fuseaction# --->") /> |
|---|
| 651 | <cfset writer.setCircuit(circuit) /> |
|---|
| 652 | <cfset writer.setFuseaction(fuseaction) /> |
|---|
| 653 | <cfif structKeyExists(this.pluginPhases,"fuseactionException") and |
|---|
| 654 | arrayLen(this.pluginPhases["fuseactionException"]) gt 0 and |
|---|
| 655 | not request.__fusebox.SuppressPlugins> |
|---|
| 656 | <cfset needTryOnFuseaction = true /> |
|---|
| 657 | <cfset writer.rawPrintln("<cftry>") /> |
|---|
| 658 | </cfif> |
|---|
| 659 | <cfif structKeyExists(this.pluginPhases,"preFuseaction")> |
|---|
| 660 | <cfset n = arrayLen(this.pluginPhases["preFuseaction"]) /> |
|---|
| 661 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 662 | <cfset this.pluginPhases["preFuseaction"][i].compile(writer) /> |
|---|
| 663 | </cfloop> |
|---|
| 664 | </cfif> |
|---|
| 665 | <cfset writer.setPhase("requestedFuseaction") /> |
|---|
| 666 | <cfset compile(writer,circuit,fuseaction) /> |
|---|
| 667 | <cfif structKeyExists(this.pluginPhases,"postFuseaction")> |
|---|
| 668 | <cfset n = arrayLen(this.pluginPhases["postFuseaction"]) /> |
|---|
| 669 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 670 | <cfset this.pluginPhases["postFuseaction"][i].compile(writer) /> |
|---|
| 671 | </cfloop> |
|---|
| 672 | </cfif> |
|---|
| 673 | <cfif needTryOnFuseaction> |
|---|
| 674 | <cfset n = arrayLen(this.pluginPhases["fuseactionException"]) /> |
|---|
| 675 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 676 | <cfset this.pluginPhases["fuseactionException"][i].compile(writer) /> |
|---|
| 677 | </cfloop> |
|---|
| 678 | <cfset writer.rawPrintln("</cftry>") /> |
|---|
| 679 | </cfif> |
|---|
| 680 | <cfset writer.close(variables.parsedFileCache) /> |
|---|
| 681 | </cfif> |
|---|
| 682 | </cflock> |
|---|
| 683 | </cfif> |
|---|
| 684 | |
|---|
| 685 | <cfset result.parsedName = parsedName /> |
|---|
| 686 | <cfif left(parsedFile,1) is "/"> |
|---|
| 687 | <cfset result.parsedFile = parsedFile /> |
|---|
| 688 | <cfelse> |
|---|
| 689 | <cfset result.parsedFile = this.getCoreToAppRootPath() & parsedFile /> |
|---|
| 690 | </cfif> |
|---|
| 691 | <cfset result.lockName = fullParsedFile /> |
|---|
| 692 | |
|---|
| 693 | <cfreturn result /> |
|---|
| 694 | |
|---|
| 695 | </cffunction> |
|---|
| 696 | |
|---|
| 697 | <cffunction name="compile" returntype="void" access="public" output="false" |
|---|
| 698 | hint="I compile a specific fuseaction during a request (such as for a 'do' verb)."> |
|---|
| 699 | <cfargument name="writer" type="any" required="false" |
|---|
| 700 | hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." /> |
|---|
| 701 | <cfargument name="circuit" type="any" required="false" |
|---|
| 702 | hint="I am the circuit name. I am required but it's faster to specify that I am not required." /> |
|---|
| 703 | <cfargument name="fuseaction" type="any" required="false" |
|---|
| 704 | hint="I am the fuseaction name, within the specified circuit." /> |
|---|
| 705 | <cfargument name="topLevel" type="boolean" default="false" |
|---|
| 706 | hint="I specify whether or not this is a top-level (public) request." /> |
|---|
| 707 | |
|---|
| 708 | <cfset var c = "" /> |
|---|
| 709 | |
|---|
| 710 | <cfif not structKeyExists(this.circuits,arguments.circuit)> |
|---|
| 711 | <cfif this.allowImplicitCircuits> |
|---|
| 712 | <!--- FB55: attempt to create an implicit circuit ---> |
|---|
| 713 | <cfset this.circuits[arguments.circuit] = |
|---|
| 714 | createObject("component","fuseboxImplicitCircuit") |
|---|
| 715 | .init(this,arguments.circuit,arguments.writer.getMyFusebox()) /> |
|---|
| 716 | <cfelse> |
|---|
| 717 | <cfthrow type="fusebox.undefinedCircuit" |
|---|
| 718 | message="undefined Circuit" |
|---|
| 719 | detail="You specified a Circuit of #arguments.circuit# which is not defined." /> |
|---|
| 720 | </cfif> |
|---|
| 721 | </cfif> |
|---|
| 722 | <!--- FB5: development-circuit-load only reloads the requested circuit ---> |
|---|
| 723 | <cfif this.mode is "development-circuit-load"> |
|---|
| 724 | <!--- FB5: ensure we only reload each circuit once per request ---> |
|---|
| 725 | <cfif not structKeyExists(request.__fusebox.CircuitsLoaded,arguments.circuit)> |
|---|
| 726 | <cfset request.__fusebox.CircuitsLoaded[arguments.circuit] = true /> |
|---|
| 727 | <cfset this.circuits[arguments.circuit].reload(arguments.writer.getMyFusebox()) /> |
|---|
| 728 | </cfif> |
|---|
| 729 | </cfif> |
|---|
| 730 | |
|---|
| 731 | <cfset c = arguments.writer.setCircuit(arguments.circuit) /> |
|---|
| 732 | <cfset this.circuits[arguments.circuit] |
|---|
| 733 | .compile(arguments.writer,arguments.fuseaction,arguments.topLevel) /> |
|---|
| 734 | <cfset arguments.writer.setCircuit(c) /> |
|---|
| 735 | |
|---|
| 736 | </cffunction> |
|---|
| 737 | |
|---|
| 738 | <cffunction name="handleFuseboxException" returntype="boolean" access="public" output="true" |
|---|
| 739 | hint="I attempt to handle a Fusebox exception by looking for a handler file in the errortemplates/ directory. I return true if I handle the exception, else I return false."> |
|---|
| 740 | <cfargument name="cfcatch" type="any" required="true" |
|---|
| 741 | hint="I am the original cfcatch structure from the exception that fusebox5.cfm caught." /> |
|---|
| 742 | <cfargument name="attributes" type="struct" required="true" |
|---|
| 743 | hint="I am the attributes 'scope'." /> |
|---|
| 744 | <cfargument name="myFusebox" type="any" required="true" |
|---|
| 745 | hint="I am the myFusebox object." /> |
|---|
| 746 | <cfargument name="appKey" type="string" required="true" |
|---|
| 747 | hint="I am the application key object." /> |
|---|
| 748 | |
|---|
| 749 | <cfset var __handled = false /> |
|---|
| 750 | <cfset var __type = arguments.cfcatch.type /> |
|---|
| 751 | <cfset var __ext = "." & this.scriptFileDelimiter /> |
|---|
| 752 | <cfset var __errorFile = this.errortemplatesPath & __type & __ext /> |
|---|
| 753 | <cfset var __handlerExists = fileExists(expandFuseboxPath(__errorFile)) /> |
|---|
| 754 | <cfset var FUSEBOX_APPLICATION_KEY = arguments.appKey /> |
|---|
| 755 | |
|---|
| 756 | <cfloop condition="not __handlerExists and len(__type) gt 0"> |
|---|
| 757 | <cfset __type = listDeleteAt(__type,listLen(__type,"."),".") /> |
|---|
| 758 | <cfset __errorFile = this.errortemplatesPath & __type & __ext /> |
|---|
| 759 | <cfset __handlerExists = fileExists(expandFuseboxPath(__errorFile)) /> |
|---|
| 760 | </cfloop> |
|---|
| 761 | <cfif __handlerExists> |
|---|
| 762 | <cfif left(__errorFile,1) is "/"> |
|---|
| 763 | <cfinclude template="#__errorFile#" /> |
|---|
| 764 | <cfelse> |
|---|
| 765 | <cfinclude template="#getCoreToAppRootPath()##__errorFile#" /> |
|---|
| 766 | </cfif> |
|---|
| 767 | <cfset __handled = true /> |
|---|
| 768 | </cfif> |
|---|
| 769 | |
|---|
| 770 | <cfreturn __handled /> |
|---|
| 771 | |
|---|
| 772 | </cffunction> |
|---|
| 773 | |
|---|
| 774 | <cffunction name="getFuseactionFactory" returntype="any" access="public" output="false" |
|---|
| 775 | hint="I return the factory object that makes fuseaction objects for the framework."> |
|---|
| 776 | |
|---|
| 777 | <cfreturn variables.factory /> |
|---|
| 778 | |
|---|
| 779 | </cffunction> |
|---|
| 780 | |
|---|
| 781 | <cffunction name="getClassDefinition" returntype="struct" access="public" output="false" |
|---|
| 782 | hint="I return the class declaration for a given class. I throw an exception if the class has no declaration."> |
|---|
| 783 | <cfargument name="className" type="string" required="true" |
|---|
| 784 | hint="I am the name of the class whose declaration should be returned." /> |
|---|
| 785 | |
|---|
| 786 | <cfreturn this.classes[arguments.className] /> |
|---|
| 787 | |
|---|
| 788 | </cffunction> |
|---|
| 789 | |
|---|
| 790 | <cffunction name="getLexiconDefinition" returntype="any" access="public" output="false" |
|---|
| 791 | hint="I return the lexicon definition for a given namespace. I return either the internal Fusebox lexicon or a declared (Fusebox 4.1 style) lexicon."> |
|---|
| 792 | <cfargument name="namespace" type="any" required="false" |
|---|
| 793 | hint="I am the namespace of the lexicon whose definition should be returned. I am required but it's faster to specify that I am not required." /> |
|---|
| 794 | |
|---|
| 795 | <cfif arguments.namespace is variables.fuseboxLexicon.namespace> |
|---|
| 796 | <cfreturn variables.fuseboxLexicon /> |
|---|
| 797 | <cfelse> |
|---|
| 798 | <cfreturn variables.fb41Lexicons[arguments.namespace] /> |
|---|
| 799 | </cfif> |
|---|
| 800 | |
|---|
| 801 | </cffunction> |
|---|
| 802 | |
|---|
| 803 | <cffunction name="getVersion" returntype="string" access="public" output="false" |
|---|
| 804 | hint="I return the version of this Fusebox 5 object. This is the preferred way to obtain the version in Fusebox 5."> |
|---|
| 805 | |
|---|
| 806 | <cfreturn variables.fuseboxVersion /> |
|---|
| 807 | |
|---|
| 808 | </cffunction> |
|---|
| 809 | |
|---|
| 810 | <cffunction name="getAlias" returntype="any" access="public" output="false" |
|---|
| 811 | hint="I return the fake circuit alias for the application."> |
|---|
| 812 | |
|---|
| 813 | <cfreturn "$fusebox" /> |
|---|
| 814 | |
|---|
| 815 | </cffunction> |
|---|
| 816 | |
|---|
| 817 | <cffunction name="getApplication" returntype="any" access="public" output="false" |
|---|
| 818 | hint="I return the fusebox application object."> |
|---|
| 819 | |
|---|
| 820 | <cfreturn this /> |
|---|
| 821 | |
|---|
| 822 | </cffunction> |
|---|
| 823 | |
|---|
| 824 | <cffunction name="getCustomAttributes" returntype="struct" access="public" output="false" |
|---|
| 825 | hint="I return any custom attributes for the specified namespace prefix."> |
|---|
| 826 | <cfargument name="ns" type="string" required="true" |
|---|
| 827 | hint="I am the namespace for which to return custom attributes." /> |
|---|
| 828 | |
|---|
| 829 | <cfif structKeyExists(variables.customAttributes,arguments.ns)> |
|---|
| 830 | <!--- we structCopy() this so folks can't poke values back into the metadata! ---> |
|---|
| 831 | <cfreturn structCopy(variables.customAttributes[arguments.ns]) /> |
|---|
| 832 | <cfelse> |
|---|
| 833 | <cfreturn structNew() /> |
|---|
| 834 | </cfif> |
|---|
| 835 | |
|---|
| 836 | </cffunction> |
|---|
| 837 | |
|---|
| 838 | <cffunction name="getFuseboxFileExtension" returntype="string" access="public" output="false" |
|---|
| 839 | hint="I return the fusebox.xml file extension: either xml or cfm."> |
|---|
| 840 | |
|---|
| 841 | <cfreturn variables.fuseboxFileExtension /> |
|---|
| 842 | |
|---|
| 843 | </cffunction> |
|---|
| 844 | |
|---|
| 845 | <cffunction name="deleteParsedFiles" returntype="void" access="private" output="false" |
|---|
| 846 | hint="I delete all the script files in the parsed/ directory."> |
|---|
| 847 | |
|---|
| 848 | <cfset var fileQuery = 0 /> |
|---|
| 849 | <cfset var parseDir = expandFuseboxPath(this.parsePath) /> |
|---|
| 850 | |
|---|
| 851 | <cftry> |
|---|
| 852 | <cfdirectory action="list" directory="#parseDir#" |
|---|
| 853 | filter="*.#this.scriptFileDelimiter#" name="fileQuery" /> |
|---|
| 854 | <cfloop query="fileQuery"> |
|---|
| 855 | <cffile action="delete" file="#parseDir##fileQuery.name#" /> |
|---|
| 856 | </cfloop> |
|---|
| 857 | <cfcatch /> |
|---|
| 858 | </cftry> |
|---|
| 859 | |
|---|
| 860 | </cffunction> |
|---|
| 861 | |
|---|
| 862 | <cffunction name="loadCircuits" returntype="void" access="private" output="false" |
|---|
| 863 | hint="I (re)load all the circuits in an application."> |
|---|
| 864 | <cfargument name="fbCode" type="any" required="true" |
|---|
| 865 | hint="I am the parsed XML representation of the fusebox.xml file." /> |
|---|
| 866 | <cfargument name="myFusebox" type="myFusebox" required="true" |
|---|
| 867 | hint="I am the myFusebox data structure." /> |
|---|
| 868 | |
|---|
| 869 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/circuits/circuit") /> |
|---|
| 870 | <cfset var i = 0 /> |
|---|
| 871 | <cfset var n = arrayLen(children) /> |
|---|
| 872 | <cfset var previousCircuits = this.circuits /> |
|---|
| 873 | <cfset var alias = "" /> |
|---|
| 874 | <cfset var parent = "" /> |
|---|
| 875 | <cfset var relative = true /> |
|---|
| 876 | <cfset var nAttrs = 0 /> |
|---|
| 877 | |
|---|
| 878 | <cfset this.circuits = structNew() /> |
|---|
| 879 | |
|---|
| 880 | <!--- pass 1: build the circuits ---> |
|---|
| 881 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 882 | <cfif not structKeyExists(children[i].xmlAttributes,"alias")> |
|---|
| 883 | <cfthrow type="fusebox.badGrammar.requiredAttributeMissing" |
|---|
| 884 | message="Required attribute is missing" |
|---|
| 885 | detail="The attribute 'alias' is required, for a 'circuit' declaration in fusebox.xml." /> |
|---|
| 886 | </cfif> |
|---|
| 887 | <cfif not structKeyExists(children[i].xmlAttributes,"path")> |
|---|
| 888 | <cfthrow type="fusebox.badGrammar.requiredAttributeMissing" |
|---|
| 889 | message="Required attribute is missing" |
|---|
| 890 | detail="The attribute 'path' is required, for the declaration of circuit '#children[i].xmlAttributes.alias#' in fusebox.xml." /> |
|---|
| 891 | </cfif> |
|---|
| 892 | <cfif structKeyExists(children[i].xmlAttributes,"parent")> |
|---|
| 893 | <cfset parent = children[i].xmlAttributes.parent /> |
|---|
| 894 | <cfset nAttrs = 3 /> |
|---|
| 895 | <cfelse> |
|---|
| 896 | <cfset parent = "" /> |
|---|
| 897 | <cfset nAttrs = 2 /> |
|---|
| 898 | </cfif> |
|---|
| 899 | <cfif structKeyExists(children[i].xmlAttributes,"relative")> |
|---|
| 900 | <cfif listFind("true,false,yes,no",children[i].xmlAttributes.relative) eq 0> |
|---|
| 901 | <cfthrow type="fusebox.badGrammar.invalidAttributeValue" |
|---|
| 902 | message="Attribute has invalid value" |
|---|
| 903 |
|---|