root / framework / tags / fusebox5A2 / fuseboxApplication.cfc

Revision 102, 27.7 kB (checked in by scorfield, 3 years ago)

Updated version to 5.0.0.A.2.
Refactored force-load when versions differ code.
This is Alpha 2!

Line 
1<!---
2Fusebox Software License
3Version 1.0
4
5Copyright (c) 2003, 2004, 2005, 2006 The Fusebox Corporation. All rights reserved.
6
7Redistribution and use in source and binary forms, with or without modification, are permitted
8provided that the following conditions are met:
9
101. Redistributions of source code must retain the above copyright notice, this list of conditions
11   and the following disclaimer.
12
132. 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
173. 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
254. 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
295. 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
33If one or more of the above conditions are violated, then this license is immediately revoked and
34can be re-instated only upon prior written authorization of the Fusebox Corporation.
35
36THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38DISCLAIMED. IN NO EVENT SHALL THE FUSEBOX CORPORATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY
39DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
43OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44
45-------------------------------------------------------------------------------
46
47This software consists of voluntary contributions made by many individuals on behalf of the
48Fusebox 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>
Note: See TracBrowser for help on using the browser.