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