| 1 | <!--- |
|---|
| 2 | Fusebox Software License |
|---|
| 3 | Version 1.0 |
|---|
| 4 | |
|---|
| 5 | Copyright (c) 2003, 2004, 2005, 2006 The Fusebox Corporation. All rights reserved. |
|---|
| 6 | |
|---|
| 7 | Redistribution and use in source and binary forms, with or without modification, are permitted |
|---|
| 8 | provided that the following conditions are met: |
|---|
| 9 | |
|---|
| 10 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions |
|---|
| 11 | and the following disclaimer. |
|---|
| 12 | |
|---|
| 13 | 2. Redistributions in binary form or otherwise encrypted form must reproduce the above copyright |
|---|
| 14 | notice, this list of conditions and the following disclaimer in the documentation and/or other |
|---|
| 15 | materials provided with the distribution. |
|---|
| 16 | |
|---|
| 17 | 3. The end-user documentation included with the redistribution, if any, must include the following |
|---|
| 18 | acknowledgment: |
|---|
| 19 | |
|---|
| 20 | "This product includes software developed by the Fusebox Corporation (http://www.fusebox.org/)." |
|---|
| 21 | |
|---|
| 22 | Alternately, this acknowledgment may appear in the software itself, if and wherever such |
|---|
| 23 | third-party acknowledgments normally appear. |
|---|
| 24 | |
|---|
| 25 | 4. The names "Fusebox" and "Fusebox Corporation" must not be used to endorse or promote products |
|---|
| 26 | derived from this software without prior written (non-electronic) permission. For written |
|---|
| 27 | permission, please contact fusebox@fusebox.org. |
|---|
| 28 | |
|---|
| 29 | 5. Products derived from this software may not be called "Fusebox", nor may "Fusebox" appear in |
|---|
| 30 | their name, without prior written (non-electronic) permission of the Fusebox Corporation. For |
|---|
| 31 | written permission, please contact fusebox@fusebox.org. |
|---|
| 32 | |
|---|
| 33 | If one or more of the above conditions are violated, then this license is immediately revoked and |
|---|
| 34 | can be re-instated only upon prior written authorization of the Fusebox Corporation. |
|---|
| 35 | |
|---|
| 36 | THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|---|
| 37 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|---|
| 38 | DISCLAIMED. IN NO EVENT SHALL THE FUSEBOX CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
|---|
| 39 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|---|
| 40 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|---|
| 41 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|---|
| 42 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|---|
| 43 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 44 | |
|---|
| 45 | ------------------------------------------------------------------------------- |
|---|
| 46 | |
|---|
| 47 | This software consists of voluntary contributions made by many individuals on behalf of the |
|---|
| 48 | Fusebox Corporation. For more information on Fusebox, please see <http://www.fusebox.org/>. |
|---|
| 49 | |
|---|
| 50 | ---> |
|---|
| 51 | <cfcomponent extends="fuseboxBaseCircuit" output="false"> |
|---|
| 52 | |
|---|
| 53 | <cfscript> |
|---|
| 54 | // initialize the fusebox (available to be read by developers but not to be written to) |
|---|
| 55 | this.isFullyLoaded = false; |
|---|
| 56 | this.circuits = structNew(); |
|---|
| 57 | this.classes = structNew(); |
|---|
| 58 | this.lexicons = structNew(); |
|---|
| 59 | this.plugins = structNew(); |
|---|
| 60 | this.pluginphases = structNew(); |
|---|
| 61 | this.nonFatalExceptionPrefix = "INFORMATION (can be ignored): "; |
|---|
| 62 | |
|---|
| 63 | this.precedenceFormOrURL = "form"; |
|---|
| 64 | this.defaultFuseaction = ""; |
|---|
| 65 | this.fuseactionVariable = "fuseaction"; |
|---|
| 66 | this.parseWithComments = false; |
|---|
| 67 | this.ignoreBadGrammar = true; |
|---|
| 68 | this.allowLexicon = true; |
|---|
| 69 | this.useAssertions = true; |
|---|
| 70 | this.conditionalParse = false; |
|---|
| 71 | |
|---|
| 72 | this.password = ""; |
|---|
| 73 | this.mode = "production"; |
|---|
| 74 | this.scriptLanguage = "cfmx"; |
|---|
| 75 | this.scriptFileDelimiter = "cfm"; |
|---|
| 76 | this.maskedFileDelimiters = "htm,cfm,cfml,php,php4,asp,aspx"; |
|---|
| 77 | this.parseWithIndentation = this.parseWithComments; |
|---|
| 78 | </cfscript> |
|---|
| 79 | |
|---|
| 80 | <cffunction name="init" returntype="fuseboxApplication" access="public" output="false"> |
|---|
| 81 | <cfargument name="appKey" type="string" required="true" /> |
|---|
| 82 | <cfargument name="appPath" type="string" required="true" /> |
|---|
| 83 | <cfargument name="myFusebox" type="myFusebox" required="true" /> |
|---|
| 84 | |
|---|
| 85 | <cfset var myVersion = "5.0.0.A.2" /> |
|---|
| 86 | <cfset var fbXML = "" /> |
|---|
| 87 | <cfset var fbCode = "" /> |
|---|
| 88 | |
|---|
| 89 | <!--- must set factory before initializing parent! ---> |
|---|
| 90 | <cfset variables.factory = createObject("component","fuseboxFactory").init() /> |
|---|
| 91 | <cfset super.init(this,"$fusebox") /> |
|---|
| 92 | <cfset variables.fuseboxVersion = myVersion /> |
|---|
| 93 | |
|---|
| 94 | <!--- to track circuit loads on this request ---> |
|---|
| 95 | <cfparam name="request._fuseboxCircuitsLoaded" default="#structNew()#" /> |
|---|
| 96 | |
|---|
| 97 | <cfset variables.appKey = arguments.appKey /> |
|---|
| 98 | <cfset this.webrootdirectory = replace(getDirectoryFromPath(getBaseTemplatePath()),"\","/","all") /> |
|---|
| 99 | <cfset variables.coreRoot = replace(getDirectoryFromPath(getCurrentTemplatePath()),"\","/","all") /> |
|---|
| 100 | |
|---|
| 101 | <cfset this.approotdirectory = this.webrootdirectory & replace(arguments.appPath,"\","/","all") /> |
|---|
| 102 | <cfif right(this.approotdirectory,1) is not "/"> |
|---|
| 103 | <cfset this.approotdirectory = this.approotdirectory & "/" /> |
|---|
| 104 | </cfif> |
|---|
| 105 | <!--- remove pairs of directory/../ to form canonical path: ---> |
|---|
| 106 | <cfloop condition="find('/../',this.approotdirectory) gt 0"> |
|---|
| 107 | <cfset this.approotdirectory = REreplace(this.approotdirectory,"[^\.:/]*/\.\./","") /> |
|---|
| 108 | </cfloop> |
|---|
| 109 | <!--- for FB4.0 compatibility: ---> |
|---|
| 110 | <cfset this.rootdirectory = this.approotdirectory /> |
|---|
| 111 | <!--- this works on all platforms: ---> |
|---|
| 112 | <cfset this.osdelimiter = "/" /> |
|---|
| 113 | |
|---|
| 114 | <cfset this.coreToAppRootPath = relativePath(variables.coreRoot,this.approotdirectory) /> |
|---|
| 115 | <cfset this.appRootPathToCore = relativePath(this.approotdirectory,variables.coreRoot) /> |
|---|
| 116 | <cfset this.coreToWebRootPath = relativePath(variables.coreRoot,this.webrootdirectory) /> |
|---|
| 117 | <cfset this.WebRootPathToCore = relativePath(this.webrootdirectory,variables.coreRoot) /> |
|---|
| 118 | |
|---|
| 119 | <cfset this.parsePath = "parsed/" /> |
|---|
| 120 | <cfset this.parseRootPath = "../" /> |
|---|
| 121 | <cfset this.pluginsPath = "plugins/" /> |
|---|
| 122 | <cfset this.lexiconPath = "lexicon/" /> |
|---|
| 123 | <cfset this.errortemplatesPath = "errortemplates/" /> |
|---|
| 124 | |
|---|
| 125 | <cfset variables.writer = createObject("component","fuseboxWriter").init(this) /> |
|---|
| 126 | |
|---|
| 127 | <!--- attempt to load fusebox.xml(.cfm): ---> |
|---|
| 128 | <cftry> |
|---|
| 129 | |
|---|
| 130 | <cffile action="read" file="#this.approotdirectory#fusebox.xml.cfm" variable="fbXML" /> |
|---|
| 131 | |
|---|
| 132 | <cfcatch type="any"> |
|---|
| 133 | <cftry> |
|---|
| 134 | |
|---|
| 135 | <cffile action="read" file="#this.approotdirectory#fusebox.xml" variable="fbXML" /> |
|---|
| 136 | |
|---|
| 137 | <cfcatch type="any"> |
|---|
| 138 | <!--- missing fusebox xml file ---> |
|---|
| 139 | </cfcatch> |
|---|
| 140 | |
|---|
| 141 | </cftry> |
|---|
| 142 | </cfcatch> |
|---|
| 143 | |
|---|
| 144 | </cftry> |
|---|
| 145 | |
|---|
| 146 | <cftry> |
|---|
| 147 | |
|---|
| 148 | <cfset fbCode = xmlParse(fbXML) /> |
|---|
| 149 | |
|---|
| 150 | <cfcatch type="any"> |
|---|
| 151 | <!--- illformed XML ---> |
|---|
| 152 | </cfcatch> |
|---|
| 153 | |
|---|
| 154 | </cftry> |
|---|
| 155 | |
|---|
| 156 | <cfset loadParameters(fbCode) /> |
|---|
| 157 | <cfset loadLexicons(fbCode) /> |
|---|
| 158 | <cfset loadClasses(fbCode) /> |
|---|
| 159 | <cfset loadPlugins(fbCode) /> |
|---|
| 160 | <cfset loadGlobalPreAndPostProcess(fbCode) /> |
|---|
| 161 | <cfset loadCircuits(fbCode) /> |
|---|
| 162 | |
|---|
| 163 | <!--- FB5: fusebox.loadclean will delete all the parsed files ---> |
|---|
| 164 | <cfif arguments.myFusebox.parameters.clean> |
|---|
| 165 | <cfset deleteParsedFiles() /> |
|---|
| 166 | </cfif> |
|---|
| 167 | |
|---|
| 168 | <cfset this.isFullyLoaded = true /> |
|---|
| 169 | <cfset this.applicationStarted = false /> |
|---|
| 170 | <cfset this.timestamp = now() /> |
|---|
| 171 | |
|---|
| 172 | <!--- |
|---|
| 173 | The following documented parts of application.fusebox are not supported in Fusebox 5: |
|---|
| 174 | - application.fusebox.xml |
|---|
| 175 | - application.fusebox.globalfuseactions.* |
|---|
| 176 | - application.fusebox.circuits.*.xml |
|---|
| 177 | - application.fusebox.circuits.preFuseaction.* |
|---|
| 178 | - application.fusebox.circuits.postFuseaction.* |
|---|
| 179 | - application.fusebox.circuits.*.fuseactions.*.xml |
|---|
| 180 | ---> |
|---|
| 181 | |
|---|
| 182 | <cfreturn this /> |
|---|
| 183 | |
|---|
| 184 | </cffunction> |
|---|
| 185 | |
|---|
| 186 | <cffunction name="getPluginsPath" returntype="string" access="public" output="false"> |
|---|
| 187 | |
|---|
| 188 | <cfreturn this.pluginsPath /> |
|---|
| 189 | |
|---|
| 190 | </cffunction> |
|---|
| 191 | |
|---|
| 192 | <cffunction name="getApplicationRoot" returntype="string" access="public" output="false"> |
|---|
| 193 | |
|---|
| 194 | <cfreturn this.approotdirectory /> |
|---|
| 195 | |
|---|
| 196 | </cffunction> |
|---|
| 197 | |
|---|
| 198 | <cffunction name="getCoreToAppRootPath" returntype="string" access="public" output="false"> |
|---|
| 199 | |
|---|
| 200 | <cfreturn this.coreToAppRootPath /> |
|---|
| 201 | |
|---|
| 202 | </cffunction> |
|---|
| 203 | |
|---|
| 204 | <cffunction name="compileAll" returntype="void" access="public" output="false"> |
|---|
| 205 | <cfargument name="myFusebox" type="myFusebox" required="true" /> |
|---|
| 206 | |
|---|
| 207 | <cfset var c = 0 /> |
|---|
| 208 | <cfset var a = 0 /> |
|---|
| 209 | <cfset var f = 0 /> |
|---|
| 210 | |
|---|
| 211 | <cfloop collection="#this.circuits#" item="c"> |
|---|
| 212 | <cfset a = this.circuits[c].getFuseactions() /> |
|---|
| 213 | <cfloop collection="#a#" item="f"> |
|---|
| 214 | <cfif a[f].access is "public"> |
|---|
| 215 | <cfset compileRequest(c & "." & f,arguments.myFusebox) /> |
|---|
| 216 | </cfif> |
|---|
| 217 | </cfloop> |
|---|
| 218 | </cfloop> |
|---|
| 219 | |
|---|
| 220 | </cffunction> |
|---|
| 221 | |
|---|
| 222 | <cffunction name="compileRequest" returntype="string" access="public" output="false"> |
|---|
| 223 | <cfargument name="circuitFuseaction" type="string" required="true" /> |
|---|
| 224 | <cfargument name="myFusebox" type="myFusebox" required="true" /> |
|---|
| 225 | |
|---|
| 226 | <cfset var myVersion = getVersion() /> |
|---|
| 227 | <cfset var circuit = listFirst(arguments.circuitFuseaction,".") /> |
|---|
| 228 | <cfset var fuseaction = listLast(arguments.circuitFuseaction,".") /> |
|---|
| 229 | <cfset var i = 0 /> |
|---|
| 230 | <cfset var n = 0 /> |
|---|
| 231 | <cfset var needRethrow = true /> |
|---|
| 232 | <cfset var needTryOnFuseaction = false /> |
|---|
| 233 | <cfset var parsedName = "#arguments.circuitFuseaction#.cfm" /> |
|---|
| 234 | <cfset var parsedFile = "#this.getCoreToAppRootPath()##this.parsePath##parsedName#" /> |
|---|
| 235 | <cfset var fullParsedFile = "#this.getApplicationRoot()##this.parsePath##parsedName#" /> |
|---|
| 236 | |
|---|
| 237 | <!--- to track reloads on this request ---> |
|---|
| 238 | <cfparam name="request._fuseboxCircuitsLoaded" default="#structNew()#" /> |
|---|
| 239 | |
|---|
| 240 | <!--- set up myFusebox values for this request: ---> |
|---|
| 241 | <cfset arguments.myFusebox.originalCircuit = circuit /> |
|---|
| 242 | <cfset arguments.myFusebox.originalFuseaction = fuseaction /> |
|---|
| 243 | <cfloop collection="#this.plugins#" item="i"> |
|---|
| 244 | <cfset arguments.myFusebox.plugins[i] = structNew() /> |
|---|
| 245 | </cfloop> |
|---|
| 246 | <cfif this.precedenceFormOrURL is "URL"> |
|---|
| 247 | <cfset arguments.myFusebox.overrideAttributes(URL) /> |
|---|
| 248 | </cfif> |
|---|
| 249 | <!--- note that in Fusebox 5, these are really all the same set of files ---> |
|---|
| 250 | <cfset arguments.myFusebox.version.loader = myVersion /> |
|---|
| 251 | <cfset arguments.myFusebox.version.parser = myVersion /> |
|---|
| 252 | <cfset arguments.myFusebox.version.transformer = myVersion /> |
|---|
| 253 | <!--- legacy test from FB41 although it's a bit pointless ---> |
|---|
| 254 | <cfif myFusebox.version.runtime neq myFusebox.version.loader> |
|---|
| 255 | <cfthrow type="fusebox.versionMismatchException" |
|---|
| 256 | message="The loader is not the same version as the runtime" /> |
|---|
| 257 | </cfif> |
|---|
| 258 | |
|---|
| 259 | <!--- check access on request - if the circuit/fuseaction doesn't exist we trap it later ---> |
|---|
| 260 | <cfif structKeyExists(this.circuits,circuit) and |
|---|
| 261 | structKeyExists(this.circuits[circuit].fuseactions,fuseaction) and |
|---|
| 262 | this.circuits[circuit].fuseactions[fuseaction].getAccess() is not "public"> |
|---|
| 263 | <cfthrow type="fusebox.invalidAccessModifier" |
|---|
| 264 | message="Invalid Access Modifier" |
|---|
| 265 | 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."> |
|---|
| 266 | </cfif> |
|---|
| 267 | |
|---|
| 268 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 269 | <cflock name="#fullParsedFile#" type="exclusive" timeout="30"> |
|---|
| 270 | <cfif not fileExists(fullParsedFile) or arguments.myFusebox.parameters.parse> |
|---|
| 271 | <cfset variables.writer.open(parsedName) /> |
|---|
| 272 | <cfset variables.writer.rawPrintln("<!--- circuit: #circuit# --->") /> |
|---|
| 273 | <cfset variables.writer.rawPrintln("<!--- fuseaction: #fuseaction# --->") /> |
|---|
| 274 | <cfset variables.writer.rawPrintln("<cftry>") /> |
|---|
| 275 | <cfset variables.writer.setCircuit(circuit) /> |
|---|
| 276 | <cfset variables.writer.setFuseaction(fuseaction) /> |
|---|
| 277 | <cfif variables.hasProcess["appinit"]> |
|---|
| 278 | <cfset variables.writer.setPhase("appinit") /> |
|---|
| 279 | <cfset variables.writer.println("<cfif myFusebox.applicationStart>") /> |
|---|
| 280 | <cfset variables.writer.println(' <cfif not myFusebox.getApplication().applicationStarted>') /> |
|---|
| 281 | <cfset variables.writer.println(' <cflock name="##application.ApplicationName##_fusebox_##FUSEBOX_APPLICATION_KEY##" type="exclusive" timeout="30">') /> |
|---|
| 282 | <cfset variables.writer.println(' <cfif not myFusebox.getApplication().applicationStarted>') /> |
|---|
| 283 | <cfset variables.process["appinit"].compile(variables.writer) /> |
|---|
| 284 | <cfset variables.writer.println(' <cfset myFusebox.getApplication().applicationStarted = true />') /> |
|---|
| 285 | <cfset variables.writer.println(' </cfif>') /> |
|---|
| 286 | <cfset variables.writer.println(' </cflock>') /> |
|---|
| 287 | <cfset variables.writer.println(' </cfif>') /> |
|---|
| 288 | <cfset variables.writer.println("</cfif>") /> |
|---|
| 289 | </cfif> |
|---|
| 290 | <cfif structKeyExists(this.pluginPhases,"preProcess")> |
|---|
| 291 | <cfset n = arrayLen(this.pluginPhases["preProcess"]) /> |
|---|
| 292 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 293 | <cfset this.pluginPhases["preProcess"][i].compile(variables.writer) /> |
|---|
| 294 | </cfloop> |
|---|
| 295 | </cfif> |
|---|
| 296 | <cfset variables.writer.setPhase("preprocessFuseactions") /> |
|---|
| 297 | <cfif variables.hasProcess["preprocess"]> |
|---|
| 298 | <cfset variables.process["preprocess"].compile(variables.writer) /> |
|---|
| 299 | </cfif> |
|---|
| 300 | <cfif structKeyExists(this.pluginPhases,"fuseactionException") and |
|---|
| 301 | arrayLen(this.pluginPhases["fuseactionException"]) gt 0> |
|---|
| 302 | <cfset needTryOnFuseaction = true /> |
|---|
| 303 | <cfset variables.writer.rawPrintln("<cftry>") /> |
|---|
| 304 | </cfif> |
|---|
| 305 | <cfif structKeyExists(this.pluginPhases,"preFuseaction")> |
|---|
| 306 | <cfset n = arrayLen(this.pluginPhases["preFuseaction"]) /> |
|---|
| 307 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 308 | <cfset this.pluginPhases["preFuseaction"][i].compile(variables.writer) /> |
|---|
| 309 | </cfloop> |
|---|
| 310 | </cfif> |
|---|
| 311 | <cfset variables.writer.setPhase("requestedFuseaction") /> |
|---|
| 312 | <cfset compile(circuit,fuseaction) /> |
|---|
| 313 | <cfif structKeyExists(this.pluginPhases,"postFuseaction")> |
|---|
| 314 | <cfset n = arrayLen(this.pluginPhases["postFuseaction"]) /> |
|---|
| 315 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 316 | <cfset this.pluginPhases["postFuseaction"][i].compile(variables.writer) /> |
|---|
| 317 | </cfloop> |
|---|
| 318 | </cfif> |
|---|
| 319 | <cfif needTryOnFuseaction> |
|---|
| 320 | <cfset n = arrayLen(this.pluginPhases["fuseactionException"]) /> |
|---|
| 321 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 322 | <cfset this.pluginPhases["fuseactionException"][i].compile(variables.writer) /> |
|---|
| 323 | </cfloop> |
|---|
| 324 | <cfset variables.writer.rawPrintln("</cftry>") /> |
|---|
| 325 | </cfif> |
|---|
| 326 | <cfset variables.writer.setPhase("postprocessFuseactions") /> |
|---|
| 327 | <cfif variables.hasProcess["postprocess"]> |
|---|
| 328 | <cfset variables.process["postprocess"].compile(variables.writer) /> |
|---|
| 329 | </cfif> |
|---|
| 330 | <cfif structKeyExists(this.pluginPhases,"postProcess")> |
|---|
| 331 | <cfset n = arrayLen(this.pluginPhases["postProcess"]) /> |
|---|
| 332 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 333 | <cfset this.pluginPhases["postProcess"][i].compile(variables.writer) /> |
|---|
| 334 | </cfloop> |
|---|
| 335 | </cfif> |
|---|
| 336 | <cfif structKeyExists(this.pluginPhases,"processError")> |
|---|
| 337 | <cfset n = arrayLen(this.pluginPhases["processError"]) /> |
|---|
| 338 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 339 | <cfset needRethrow = false /> |
|---|
| 340 | <cfset this.pluginPhases["processError"][i].compile(variables.writer) /> |
|---|
| 341 | </cfloop> |
|---|
| 342 | </cfif> |
|---|
| 343 | <cfif needRethrow> |
|---|
| 344 | <cfset variables.writer.rawPrintln('<' & 'cfcatch><' & 'cfrethrow><' & '/cfcatch>') /> |
|---|
| 345 | </cfif> |
|---|
| 346 | <cfset variables.writer.rawPrintln("</cftry>") /> |
|---|
| 347 | <cfset variables.writer.close() /> |
|---|
| 348 | </cfif> |
|---|
| 349 | </cflock> |
|---|
| 350 | </cfif> |
|---|
| 351 | |
|---|
| 352 | <cfreturn parsedFile /> |
|---|
| 353 | |
|---|
| 354 | </cffunction> |
|---|
| 355 | |
|---|
| 356 | <cffunction name="compile" returntype="void" access="public" output="false"> |
|---|
| 357 | <cfargument name="circuit" type="string" required="true" /> |
|---|
| 358 | <cfargument name="fuseaction" type="string" required="true" /> |
|---|
| 359 | |
|---|
| 360 | <cfset var c = "" /> |
|---|
| 361 | |
|---|
| 362 | <cfif not structKeyExists(this.circuits,arguments.circuit)> |
|---|
| 363 | <cfthrow type="fusebox.undefinedCircuit" |
|---|
| 364 | message="undefined Circuit" |
|---|
| 365 | detail="You specified a Circuit of #arguments.circuit# which is not defined." /> |
|---|
| 366 | </cfif> |
|---|
| 367 | <!--- FB5: development-no-load only reloads the requested circuit ---> |
|---|
| 368 | <cfif this.mode is "development-no-load"> |
|---|
| 369 | <!--- FB5: ensure we only reload each circuit once per request ---> |
|---|
| 370 | <cfif not structKeyExists(request._fuseboxCircuitsLoaded,arguments.circuit)> |
|---|
| 371 | <cfset request._fuseboxCircuitsLoaded[arguments.circuit] = true /> |
|---|
| 372 | <cfset this.circuits[arguments.circuit].reload(variables.appKey) /> |
|---|
| 373 | </cfif> |
|---|
| 374 | </cfif> |
|---|
| 375 | |
|---|
| 376 | <cfset c = variables.writer.setCircuit(arguments.circuit) /> |
|---|
| 377 | <cfset this.circuits[arguments.circuit] |
|---|
| 378 | .compile(variables.writer,arguments.fuseaction) /> |
|---|
| 379 | <cfset variables.writer.setCircuit(c) /> |
|---|
| 380 | |
|---|
| 381 | </cffunction> |
|---|
| 382 | |
|---|
| 383 | <cffunction name="handleFuseboxException" returntype="boolean" access="public" output="true"> |
|---|
| 384 | <cfargument name="cfcatch" type="any" required="true" /> |
|---|
| 385 | |
|---|
| 386 | <cfset var handled = false /> |
|---|
| 387 | <cfset var type = cfcatch.type /> |
|---|
| 388 | <cfset var ext = "." & this.scriptFileDelimiter /> |
|---|
| 389 | <cfset var errorFile = this.errortemplatesPath & type & ext /> |
|---|
| 390 | <cfset var handlerExists = fileExists(getApplicationRoot() & errorFile) /> |
|---|
| 391 | <cfset var FUSEBOX_APPLICATION_KEY = variables.appKey /> |
|---|
| 392 | |
|---|
| 393 | <cfloop condition="not handlerExists and len(type) gt 0"> |
|---|
| 394 | <cfset type = listDeleteAt(type,listLen(type,"."),".") /> |
|---|
| 395 | <cfset errorFile = this.errortemplatesPath & type & ext /> |
|---|
| 396 | <cfset handlerExists = fileExists(getApplicationRoot() & errorFile) /> |
|---|
| 397 | </cfloop> |
|---|
| 398 | <cfif handlerExists> |
|---|
| 399 | <cfinclude template="#getCoreToAppRootPath()##errorFile#" /> |
|---|
| 400 | <cfset handled = true /> |
|---|
| 401 | </cfif> |
|---|
| 402 | |
|---|
| 403 | <cfreturn handled /> |
|---|
| 404 | |
|---|
| 405 | </cffunction> |
|---|
| 406 | |
|---|
| 407 | <cffunction name="getFuseactionFactory" returntype="struct" access="public" output="false"> |
|---|
| 408 | |
|---|
| 409 | <cfreturn variables.factory /> |
|---|
| 410 | |
|---|
| 411 | </cffunction> |
|---|
| 412 | |
|---|
| 413 | <cffunction name="getClassDefinition" returntype="struct" access="public" output="false"> |
|---|
| 414 | <cfargument name="className" type="string" required="true" /> |
|---|
| 415 | |
|---|
| 416 | <cfreturn this.classes[arguments.className] /> |
|---|
| 417 | |
|---|
| 418 | </cffunction> |
|---|
| 419 | |
|---|
| 420 | <cffunction name="getLexiconDefinition" returntype="struct" access="public" output="false"> |
|---|
| 421 | <cfargument name="namespace" type="string" required="true" /> |
|---|
| 422 | |
|---|
| 423 | <cfif arguments.namespace is getFuseboxLexicon().namespace> |
|---|
| 424 | <cfreturn getFuseboxLexicon() /> |
|---|
| 425 | <cfelse> |
|---|
| 426 | <cfreturn variables.fb41Lexicons[arguments.namespace] /> |
|---|
| 427 | </cfif> |
|---|
| 428 | |
|---|
| 429 | </cffunction> |
|---|
| 430 | |
|---|
| 431 | <cffunction name="getLexicons" returntype="struct" access="public" output="false"> |
|---|
| 432 | |
|---|
| 433 | <cfreturn variables.fb41Lexicons /> |
|---|
| 434 | |
|---|
| 435 | </cffunction> |
|---|
| 436 | |
|---|
| 437 | <cffunction name="getVersion" returntype="string" access="public" output="false"> |
|---|
| 438 | |
|---|
| 439 | <cfreturn variables.fuseboxVersion /> |
|---|
| 440 | |
|---|
| 441 | </cffunction> |
|---|
| 442 | |
|---|
| 443 | <cffunction name="deleteParsedFiles" returntype="void" access="private" output="false"> |
|---|
| 444 | |
|---|
| 445 | <cfset var fileQuery = 0 /> |
|---|
| 446 | <cfset var parseDir = getApplicationRoot() & this.parsePath /> |
|---|
| 447 | |
|---|
| 448 | <cftry> |
|---|
| 449 | <cfdirectory action="list" directory="#parseDir#" |
|---|
| 450 | filter="*.#this.scriptFileDelimiter#" name="fileQuery" /> |
|---|
| 451 | <cfloop query="fileQuery"> |
|---|
| 452 | <cffile action="delete" file="#parseDir##fileQuery.name#" /> |
|---|
| 453 | </cfloop> |
|---|
| 454 | <cfcatch /> |
|---|
| 455 | </cftry> |
|---|
| 456 | |
|---|
| 457 | </cffunction> |
|---|
| 458 | |
|---|
| 459 | <cffunction name="loadCircuits" returntype="void" access="private" output="false"> |
|---|
| 460 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 461 | |
|---|
| 462 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/circuits/circuit") /> |
|---|
| 463 | <cfset var i = 0 /> |
|---|
| 464 | <cfset var n = arrayLen(children) /> |
|---|
| 465 | |
|---|
| 466 | <cfset this.circuits = structNew() /> |
|---|
| 467 | |
|---|
| 468 | <!--- pass 1: build the circuits ---> |
|---|
| 469 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 470 | <!--- record each circuit load per request - optimization for development-no-load mode ---> |
|---|
| 471 | <cfset request._fuseboxCircuitsLoaded[children[i].xmlAttributes.alias] = true /> |
|---|
| 472 | <cfparam name="children[i].xmlAttributes.parent" type="string" default="" /> |
|---|
| 473 | <cfset this.circuits[ children[i].xmlAttributes.alias ] = |
|---|
| 474 | createObject("component","fuseboxCircuit") |
|---|
| 475 | .init(this, |
|---|
| 476 | children[i].xmlAttributes.alias, |
|---|
| 477 | children[i].xmlAttributes.path, |
|---|
| 478 | children[i].xmlAttributes.parent) /> |
|---|
| 479 | </cfloop> |
|---|
| 480 | |
|---|
| 481 | <!--- pass 2: build the circuit trace for each circuit ---> |
|---|
| 482 | <cfloop collection="#this.circuits#" item="i"> |
|---|
| 483 | <cfset this.circuits[i].buildCircuitTrace() /> |
|---|
| 484 | </cfloop> |
|---|
| 485 | |
|---|
| 486 | </cffunction> |
|---|
| 487 | |
|---|
| 488 | <cffunction name="loadLexicons" returntype="void" access="private" output="false"> |
|---|
| 489 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 490 | |
|---|
| 491 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/lexicons/lexicon") /> |
|---|
| 492 | <cfset var i = 0 /> |
|---|
| 493 | <cfset var n = arrayLen(children) /> |
|---|
| 494 | <cfset var aLex = "" /> |
|---|
| 495 | <cfset var attributes = arguments.fbCode.xmlRoot.xmlAttributes /> |
|---|
| 496 | <cfset var attr = "" /> |
|---|
| 497 | <cfset var ns = "" /> |
|---|
| 498 | |
|---|
| 499 | <!--- load the legacy FB41 lexicons from the XML ---> |
|---|
| 500 | <cfset variables.fb41Lexicons = structNew() /> |
|---|
| 501 | |
|---|
| 502 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 503 | <cfset aLex = structNew() /> |
|---|
| 504 | <cfset aLex.namespace = children[i].xmlAttributes.namespace /> |
|---|
| 505 | <cfset aLex.path = replace(children[i].xmlAttributes.path,"\","/","all") /> |
|---|
| 506 | <cfif right(aLex.path,1) is not "/"> |
|---|
| 507 | <cfset aLex.path = aLex.path & "/" /> |
|---|
| 508 | </cfif> |
|---|
| 509 | <cfset aLex.path = getCoreToAppRootPath() & "lexicon/" & aLex.path /> |
|---|
| 510 | <cfset variables.fb41Lexicons[children[i].xmlAttributes.namespace] = aLex /> |
|---|
| 511 | </cfloop> |
|---|
| 512 | |
|---|
| 513 | <!--- now load the new FB5 implicit lexicons from the <fusebox> tag ---> |
|---|
| 514 | |
|---|
| 515 | <!--- pass 1: pull out any namespace declarations ---> |
|---|
| 516 | <cfloop collection="#attributes#" item="attr"> |
|---|
| 517 | <cfif len(attr) gt 6 and left(attr,6) is "xmlns:"> |
|---|
| 518 | <!--- found a namespace declaration, pull it out: ---> |
|---|
| 519 | <cfset aLex = structNew() /> |
|---|
| 520 | <cfset aLex.namespace = listLast(attr,":") /> |
|---|
| 521 | <cfif aLex.namespace is getFuseboxLexicon().namespace> |
|---|
| 522 | <cfthrow type="fusebox.badGrammar.reservedName" |
|---|
| 523 | message="Attempt to use reserved namespace" |
|---|
| 524 | detail="You have attempted to declare a namespace '#aLex.namespace#' (in fusebox.xml) which is reserved by the Fusebox framework." /> |
|---|
| 525 | </cfif> |
|---|
| 526 | <cfset aLex.path = getApplication().getCoreToAppRootPath() & getApplication().lexiconPath & attributes[attr] /> |
|---|
| 527 | <cfset variables.lexicons[aLex.namespace] = aLex /> |
|---|
| 528 | <cfset variables.customAttributes[aLex.namespace] = structNew() /> |
|---|
| 529 | </cfif> |
|---|
| 530 | </cfloop> |
|---|
| 531 | |
|---|
| 532 | <!--- pass 2: pull out any custom attributes ---> |
|---|
| 533 | <cfloop collection="#attributes#" item="attr"> |
|---|
| 534 | <cfif listLen(attr,":") eq 2> |
|---|
| 535 | <!--- looks like a custom attribute: ---> |
|---|
| 536 | <cfset ns = listFirst(attr,":") /> |
|---|
| 537 | <cfif ns is "xmlns"> |
|---|
| 538 | <!--- special case - need to ignore xmlns:foo="bar" ---> |
|---|
| 539 | <cfelseif structKeyExists(variables.customAttributes,ns)> |
|---|
| 540 | <cfset variables.customAttributes[ns][listLast(attr,":")] = attributes[attr] /> |
|---|
| 541 | <cfelse> |
|---|
| 542 | <!--- TODO: error: undeclared namespace ---> |
|---|
| 543 | </cfif> |
|---|
| 544 | </cfif> |
|---|
| 545 | </cfloop> |
|---|
| 546 | |
|---|
| 547 | </cffunction> |
|---|
| 548 | |
|---|
| 549 | <cffunction name="loadClasses" returntype="void" access="private" output="false"> |
|---|
| 550 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 551 | |
|---|
| 552 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/classes/class") /> |
|---|
| 553 | <cfset var i = 0 /> |
|---|
| 554 | <cfset var n = arrayLen(children) /> |
|---|
| 555 | <cfset var attribs = 0 /> |
|---|
| 556 | <cfset var attr = "" /> |
|---|
| 557 | <cfset var ns = "" /> |
|---|
| 558 | <cfset var customAttribs = 0 /> |
|---|
| 559 | |
|---|
| 560 | <cfset this.classes = structNew() /> |
|---|
| 561 | |
|---|
| 562 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 563 | <cfset attribs = children[i].xmlAttributes /> |
|---|
| 564 | |
|---|
| 565 | <cfparam name="attribs.constructor" type="string" default="" /> |
|---|
| 566 | <!--- FB5: allow sensible default for type ---> |
|---|
| 567 | <cfparam name="attribs.type" type="string" default="component" /> |
|---|
| 568 | |
|---|
| 569 | <!--- scan for custom attributes ---> |
|---|
| 570 | <cfset customAttribs = structNew() /> |
|---|
| 571 | <cfloop collection="#attribs#" item="attr"> |
|---|
| 572 | <cfif listLen(attr,":") eq 2> |
|---|
| 573 | <!--- looks like a custom attribute: ---> |
|---|
| 574 | <cfset ns = listFirst(attr,":") /> |
|---|
| 575 | <cfif structKeyExists(variables.customAttributes,ns)> |
|---|
| 576 | <cfset customAttribs[ns][listLast(attr,":")] = attribs[attr] /> |
|---|
| 577 | <cfelse> |
|---|
| 578 | <!--- TODO: error: undeclared namespace ---> |
|---|
| 579 | </cfif> |
|---|
| 580 | </cfif> |
|---|
| 581 | </cfloop> |
|---|
| 582 | |
|---|
| 583 | <cfset this.classes[attribs.alias] = createObject("component","fuseboxClassDefinition") |
|---|
| 584 | .init(attribs.type,attribs.classpath,attribs.constructor,customAttribs) /> |
|---|
| 585 | |
|---|
| 586 | </cfloop> |
|---|
| 587 | |
|---|
| 588 | </cffunction> |
|---|
| 589 | |
|---|
| 590 | <cffunction name="loadPlugins" returntype="void" access="private" output="false"> |
|---|
| 591 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 592 | |
|---|
| 593 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/plugins/phase") /> |
|---|
| 594 | <cfset var i = 0 /> |
|---|
| 595 | <cfset var n = arrayLen(children) /> |
|---|
| 596 | <cfset var j = 0 /> |
|---|
| 597 | <cfset var nn = 0 /> |
|---|
| 598 | <cfset var phase = "" /> |
|---|
| 599 | <cfset var plugin = 0 /> |
|---|
| 600 | |
|---|
| 601 | <cfset this.plugins = structNew() /> |
|---|
| 602 | <cfset this.pluginphases = structNew() /> |
|---|
| 603 | |
|---|
| 604 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 605 | <cfset phase = children[i].xmlAttributes.name /> |
|---|
| 606 | <cfset nn = arrayLen(children[i].xmlChildren) /> |
|---|
| 607 | <cfloop from="1" to="#nn#" index="j"> |
|---|
| 608 | <cfset plugin = createObject("component","fuseboxPlugin").init(phase,children[i].xmlChildren[j],this) /> |
|---|
| 609 | <cfset this.plugins[plugin.getName()][phase] = plugin /> |
|---|
| 610 | <cfif not structKeyExists(this.pluginphases,phase)> |
|---|
| 611 | <cfset this.pluginphases[phase] = arrayNew(1) /> |
|---|
| 612 | </cfif> |
|---|
| 613 | <cfset arrayAppend(this.pluginphases[phase],plugin) /> |
|---|
| 614 | </cfloop> |
|---|
| 615 | </cfloop> |
|---|
| 616 | |
|---|
| 617 | </cffunction> |
|---|
| 618 | |
|---|
| 619 | <cffunction name="loadParameters" returntype="void" access="private" output="false"> |
|---|
| 620 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 621 | |
|---|
| 622 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/parameters/parameter") /> |
|---|
| 623 | <cfset var i = 0 /> |
|---|
| 624 | <cfset var n = arrayLen(children) /> |
|---|
| 625 | <cfset var p = "" /> |
|---|
| 626 | |
|---|
| 627 | <cfloop from="1" to="#n#" index="i"> |
|---|
| 628 | <cfset p = children[i].xmlAttributes.name /> |
|---|
| 629 | <cfif structKeyExists(this,p) and isCustomFunction(this[p])> |
|---|
| 630 | <cfthrow type="fusebox.badGrammar.reservedName" |
|---|
| 631 | message="Attempt to use reserved parameter name" |
|---|
| 632 | detail="You have attempted to set a parameter called '#p#' which is reserved by the Fusebox framework." /> |
|---|
| 633 | <cfelse> |
|---|
| 634 | <cfset this[p] = children[i].xmlAttributes.value /> |
|---|
| 635 | </cfif> |
|---|
| 636 | </cfloop> |
|---|
| 637 | |
|---|
| 638 | </cffunction> |
|---|
| 639 | |
|---|
| 640 | <cffunction name="loadGlobalProcess" returntype="void" access="private" output="false"> |
|---|
| 641 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 642 | <cfargument name="processPhase" type="string" required="true" /> |
|---|
| 643 | |
|---|
| 644 | <cfset var children = xmlSearch(arguments.fbCode,"/fusebox/globalfuseactions/#arguments.processPhase#") /> |
|---|
| 645 | <cfset var i = 0 /> |
|---|
| 646 | <cfset var n = arrayLen(children) /> |
|---|
| 647 | |
|---|
| 648 | <cfif n eq 0> |
|---|
| 649 | <cfset variables.hasProcess[arguments.processPhase] = false /> |
|---|
| 650 | <cfelseif n eq 1> |
|---|
| 651 | <cfset variables.hasProcess[arguments.processPhase] = true /> |
|---|
| 652 | <cfset variables.process[arguments.processPhase] = |
|---|
| 653 | createObject("component","fuseboxAction") |
|---|
| 654 | .init(this, |
|---|
| 655 | "$globalfuseaction/#arguments.processPhase#", |
|---|
| 656 | "internal", |
|---|
| 657 | children[1].xmlChildren,true) /> |
|---|
| 658 | <cfelse> |
|---|
| 659 | <!--- TODO: ought to check there is only one globalpre/postprocess? ---> |
|---|
| 660 | </cfif> |
|---|
| 661 | |
|---|
| 662 | </cffunction> |
|---|
| 663 | |
|---|
| 664 | <cffunction name="loadGlobalPreAndPostProcess" returntype="void" access="private" output="false"> |
|---|
| 665 | <cfargument name="fbCode" type="any" required="true" /> |
|---|
| 666 | |
|---|
| 667 | <cfset variables.hasProcess = structNew() /> |
|---|
| 668 | <cfset variables.process = structNew() /> |
|---|
| 669 | <cfset loadGlobalProcess(arguments.fbCode,"appinit") /> |
|---|
| 670 | <cfset loadGlobalProcess(arguments.fbCode,"preprocess") /> |
|---|
| 671 | <cfset loadGlobalProcess(arguments.fbCode,"postprocess") /> |
|---|
| 672 | |
|---|
| 673 | </cffunction> |
|---|
| 674 | |
|---|
| 675 | <cffunction name="relativePath" returntype="string" access="public" output="false"> |
|---|
| 676 | <cfargument name="from" type="string" required="true" /> |
|---|
| 677 | <cfargument name="to" type="string" required="true" /> |
|---|
| 678 | |
|---|
| 679 | <cfset var relative = "" /> |
|---|
| 680 | <cfset var fromFirst = listFirst(arguments.from,"/") /> |
|---|
| 681 | <cfset var fromRest = arguments.from /> |
|---|
| 682 | <cfset var toFirst = listFirst(arguments.to,"/") /> |
|---|
| 683 | <cfset var toRest = arguments.to /> |
|---|
| 684 | <cfset var needSlash = false /> |
|---|
| 685 | |
|---|
| 686 | <!--- trap special case first ---> |
|---|
| 687 | <cfif arguments.from is arguments.to> |
|---|
| 688 | <cfreturn "" /> |
|---|
| 689 | </cfif> |
|---|
| 690 | |
|---|
| 691 | <!--- walk down the common part of the paths ---> |
|---|
| 692 | <cfloop condition="fromFirst is toFirst"> |
|---|
| 693 | <cfset needSlash = true /> |
|---|
| 694 | <cfset fromRest = listRest(fromRest,"/") /> |
|---|
| 695 | <cfset toRest = listRest(toRest,"/") /> |
|---|
| 696 | <cfset fromFirst = listFirst(fromRest,"/") /> |
|---|
| 697 | <cfset toFirst = listFirst(toRest,"/") /> |
|---|
| 698 | </cfloop> |
|---|
| 699 | <!--- at this point the paths differ ---> |
|---|
| 700 | <cfif not needSlash> |
|---|
| 701 | <!--- the paths differed from the top so we need to strip the leading / ---> |
|---|
| 702 | <cfset toRest = right(toRest,len(toRest)-1) /> |
|---|
| 703 | </cfif> |
|---|
| 704 | <cfset relative = repeatString("../",listLen(fromRest,"/")) & toRest /> |
|---|
| 705 | |
|---|
| 706 | <cfreturn relative /> |
|---|
| 707 | |
|---|
| 708 | </cffunction> |
|---|
| 709 | |
|---|
| 710 | </cfcomponent> |
|---|