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