- qpscanner/fusebox5/fuseboxCircuit.cfc
- v0.7.3.1
- 26 KB
- 617
1<!---
2Copyright 2006-2007 TeraTech, Inc. http://teratech.com/
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15--->
16<cfcomponent output="false" hint="I represent a circuit.">
17
18 <cffunction name="init" returntype="fuseboxCircuit" access="public" output="false"
19 hint="I am the constructor.">
20 <cfargument name="fbApp" type="fuseboxApplication" required="true"
21 hint="I am the fusebox application object." />
22 <cfargument name="alias" type="string" required="true"
23 hint="I am the circuit alias." />
24 <cfargument name="path" type="string" required="true"
25 hint="I am the path from the application root to the circuit directory." />
26 <cfargument name="parent" type="string" required="true"
27 hint="I am the alias of the parent circuit." />
28 <cfargument name="myFusebox" type="myFusebox" required="true"
29 hint="I am the myFusebox data structure." />
30 <cfargument name="relative" type="boolean" required="true"
31 hint="I indicate whether the path is relative or absolute (mapped)." />
32
33 <cfset variables.fuseboxApplication = arguments.fbApp />
34 <cfset variables.alias = arguments.alias />
35 <cfset variables.relative = arguments.relative />
36
37 <cfset variables.fuseboxLexicon = variables.fuseboxApplication.getFuseactionFactory().getBuiltinLexicon() />
38
39 <cfset variables.customAttributes = structNew() />
40
41 <cfset variables.originalPath = arguments.path />
42 <cfset this.parent = arguments.parent />
43 <cfset variables.appPath = variables.fuseboxApplication.getApplicationRoot() />
44 <cfset variables.lexicons = structNew() />
45
46 <cfset variables.relativePath = variables.fuseboxApplication.normalizePartialPath(arguments.path) />
47 <cfset this.path = variables.relativePath />
48 <!--- ticket 139: allow absolute path names and mappings: --->
49 <cfif left(variables.relativePath,1) is "/">
50 <cfif variables.relative>
51 <!--- unintentional absolute path? --->
52 <cfif variables.fuseboxApplication.strictMode>
53 <cfthrow type="fusebox.badGrammar.illegalPath"
54 message="Circuit path is not relative"
55 detail="The 'path' value '#variables.originalPath#' for circuit #getAlias()# specifies an absolute path. Did you forget to specify 'relative=""false""'?" />
56 </cfif>
57 <cfset variables.fullPath = variables.appPath & variables.relativePath />
58 <cfelse>
59 <!--- explicit absolute / mapped path: --->
60 <cfset variables.fullPath = replace(expandPath(variables.relativePath),"\","/","all") />
61 </cfif>
62 <cfelse>
63 <cfif variables.relative>
64 <cfset variables.fullPath = variables.appPath & variables.relativePath />
65 <cfelse>
66 <cfthrow type="fusebox.badGrammar.illegalPath"
67 message="Circuit path is relative"
68 detail="The 'path' value '#variables.originalPath#' for circuit #getAlias()# should specify an absolute path when 'relative=""false""'." />
69 </cfif>
70 </cfif>
71
72 <cfset variables.fullPath = variables.fuseboxApplication.getCanonicalPath(variables.fullPath) />
73
74 <!---
75 this was not correctly normalized prior to ticket 139 but it didn't really matter
76 until absolute paths were allowed in that ticket:
77 --->
78 <cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
79 <cfset this.rootPath = variables.fuseboxApplication.relativePath(variables.fullPath,variables.appPath) />
80
81 <cfset reload(arguments.myFusebox) />
82
83 <cfreturn this />
84
85 </cffunction>
86
87 <cffunction name="reload" returntype="fuseboxCircuit" access="public" output="false"
88 hint="I reload the circuit file and build the in-memory structures from it.">
89 <cfargument name="myFusebox" type="myFusebox" required="true"
90 hint="I am the myFusebox data structure." />
91
92 <cfset var circuitFile = "circuit.xml.cfm" />
93 <cfset var circuitFileAlt = "circuit.xml" />
94 <cfset var circuitImplicit = false />
95 <cfset var circuitXML = "" />
96 <cfset var circuitCode = "" />
97 <cfset var needToLoad = true />
98 <cfset var circuitFiles = 0 />
99
100 <!---
101 since we need to check the file, regardless of whether we load it,
102 we might as well do the test up front and perform the strict check
103 that just one version exists (ticket 135)
104 --->
105 <cfif fileExists(variables.fullPath & circuitFile)>
106 <cfif variables.fuseboxApplication.strictMode and fileExists(variables.fullPath & circuitFileAlt)>
107 <cfthrow type="fusebox.multipleCircuitXML"
108 message="Both 'circuit.xml' and 'circuit.xml.cfm' exist"
109 detail="'circuit.xml.cfm' will be used but 'circuit.xml' also exists in '#variables.fullPath#." />
110 </cfif>
111 <cfelse>
112 <cfset circuitFile = circuitFileAlt />
113 </cfif>
114
115 <cfif structKeyExists(this,"timestamp")>
116 <!--- Java timestamp solution provided by Daniel Schmid --->
117 <cfset needToLoad = getApplication().fileModificationDate(variables.fullPath & circuitFile) gt parseDateTime(this.timestamp) />
118 </cfif>
119
120 <cfif needToLoad>
121 <cfif variables.fuseboxApplication.debug>
122 <cfset arguments.myFusebox.trace("Compiler","Loading #getAlias()# circuit.xml file") />
123 </cfif>
124
125 <!--- attempt to load circuit.xml(.cfm): --->
126 <cftry>
127
128 <cffile action="read" file="#variables.fullPath##circuitFile#"
129 variable="circuitXML"
130 charset="#variables.fuseboxApplication.characterEncoding#" />
131 <cfset variables.circuitPath = variables.fullPath & circuitFile />
132
133 <cfcatch type="security">
134 <!--- cffile denied by sandbox security --->
135 <cfthrow type="fusebox.security"
136 message="security error reading circuit.xml"
137 detail="The circuit xml file, '#circuitFile#', for circuit #getAlias()# could not be read because sandbox security has disabled the cffile tag."
138 extendedinfo="#cfcatch.detail#" />
139 </cfcatch>
140
141 <cfcatch type="any">
142 <cfif variables.fuseboxApplication.allowImplicitCircuits>
143 <cfset circuitXML = "<circuit/>" />
144 <cfset circuitImplicit = true />
145 <cfelse>
146 <cfthrow type="fusebox.missingCircuitXML"
147 message="missing circuit.xml"
148 detail="The circuit xml file, #circuitFile#, for circuit #getAlias()# could not be found in #variables.fullPath#."
149 extendedinfo="#cfcatch.detail#" />
150 </cfif>
151 </cfcatch>
152
153 </cftry>
154<!---
155 this was initially implemented as part of ticket 135 but feedback on
156 the mailing list seems to indicate people think it is too draconian
157 a restriction, even in strict mode - and I agree! -- Sean Corfield
158
159 <cfif variables.fuseboxApplication.strictMode and not circuitImplicit and
160 variables.fuseboxApplication.getFuseboxFileExtension() is not listLast(circuitFile,".")>
161 <cfthrow type="fusebox.inconsistentFuseboxCircuit"
162 message="Inconsistent Fusebox / Circuit file extensions"
163 detail="The circuit xml file, #circuitFile#, in #variables.fullPath#, uses a different file extension to the application's fusebox xml file. Strict requires consistency." />
164 </cfif>
165 --->
166 <cftry>
167
168 <cfset circuitCode = xmlParse(circuitXML) />
169
170 <cfcatch type="any">
171 <cfthrow type="fusebox.circuitXMLError"
172 message="Error reading circuit.xml"
173 detail="A problem was encountered while reading the circuit file #circuitFile# for circuit #getAlias()#. This is usually caused by unmatched XML tag-pairs. Close all XML tags explicitly or use the / (slash) short-cut."
174 extendedinfo="#cfcatch.detail#" />
175 </cfcatch>
176
177 </cftry>
178
179 <cfif circuitCode.xmlRoot.xmlName is not "circuit">
180 <cfthrow type="fusebox.badGrammar.badCircuitFile"
181 detail="Circuit file does contain 'circuit' XML"
182 message="Circuit file #variables.circuitPath# does not contain 'circuit' as the root XML node." />
183 </cfif>
184 <cfif structKeyExists(circuitCode.xmlRoot.xmlAttributes,"access")>
185 <cfif listFind("private,internal,public",circuitCode.xmlRoot.xmlAttributes.access) eq 0>
186 <cfthrow type="fusebox.badGrammar.illegalAccess"
187 message="Circuit access illegal"
188 detail="The 'access' value '#circuitCode.xmlRoot.xmlAttributes.access#' is illegal in Circuit #getAlias()#. 'private', 'internal' or 'public' are the only legal values." />
189 </cfif>
190 <cfset this.access = circuitCode.xmlRoot.xmlAttributes.access />
191 <cfelse>
192 <cfset this.access = "internal" />
193 </cfif>
194 <cfif structKeyExists(circuitCode.xmlRoot.xmlAttributes,"permissions")>
195 <cfset this.permissions = circuitCode.xmlRoot.xmlAttributes.permissions />
196 <cfelse>
197 <cfset this.permissions = "" />
198 </cfif>
199
200 <cfset loadLexicons(circuitCode) />
201 <cfset loadPreAndPostFuseactions(circuitCode) />
202 <cfset loadFuseactions(circuitCode) />
203 <cfset variables.circuitFile = circuitFile />
204 <cfset this.timestamp = now() />
205 </cfif>
206
207 <cfreturn this />
208
209 </cffunction>
210
211 <cffunction name="compile" returntype="void" access="public" output="false"
212 hint="I compile a given fuseaction within this circuit.">
213 <cfargument name="writer" type="any" required="false"
214 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
215 <cfargument name="fuseaction" type="any" required="false"
216 hint="I am the name of the fuseaction to compile. I am required but it's faster to specify that I am not required." />
217
218 <cfset var f = arguments.writer.setFuseaction(arguments.fuseaction) />
219
220 <cfset compilePreOrPostFuseaction(arguments.writer,"pre") />
221
222 <cfif not structKeyExists(this.fuseactions,arguments.fuseaction)>
223 <cfthrow type="fusebox.undefinedFuseaction"
224 message="undefined Fuseaction"
225 detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
226 </cfif>
227 <cfset this.fuseactions[arguments.fuseaction].compile(arguments.writer) />
228
229 <cfset compilePreOrPostFuseaction(arguments.writer,"post") />
230
231 <cfset arguments.writer.setFuseaction(f) />
232
233 </cffunction>
234
235 <cffunction name="compilePreOrPostFuseaction" returntype="void" access="public" output="false"
236 hint="I compile the pre/post-fuseaction for a circuit.">
237 <cfargument name="writer" type="any" required="false"
238 hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
239 <cfargument name="preOrPost" type="string" required="false"
240 hint="I am either 'pre' or 'post' to indicate whether this is a prefuseaction or a postfuseaction. I am required but it's faster to specify that I am not required." />
241
242 <cfset var c = "" />
243
244 <cfif variables.hasAction[arguments.preOrPost]>
245 <cfif arguments.preOrPost is "pre" and variables.callsuper["pre"] and hasParent()>
246 <cfset getParent().compilePreOrPostFuseaction(arguments.writer,arguments.preOrPost) />
247 </cfif>
248 <cfset c = arguments.writer.setCircuit(getAlias()) />
249 <cfset variables.action[arguments.preOrPost].compile(arguments.writer) />
250 <cfset arguments.writer.setCircuit(c) />
251 <cfif arguments.preOrPost is "post" and variables.callsuper["post"] and hasParent()>
252 <cfset getParent().compilePreOrPostFuseaction(arguments.writer,arguments.preOrPost) />
253 </cfif>
254 </cfif>
255
256 </cffunction>
257
258 <cffunction name="buildCircuitTrace" returntype="void" access="public" output="false"
259 hint="I build the 'circuit trace' structure - the array of parents. Required for Fusebox 4.1 compatibility.">
260
261 <cfset var c = getParentName() />
262 <cfset var seen = structNew() />
263
264 <cfset seen[getAlias()] = true />
265 <cfset this.circuitTrace = arrayNew(1) />
266 <cfset arrayAppend(this.circuitTrace,getAlias()) />
267 <cfloop condition="c is not ''">
268 <cfif structKeyExists(seen,c)>
269 <cfthrow type="fusebox.badGrammar.circularParent"
270 message="Circular parent for Circuit"
271 detail="You specified a parent Circuit of #c# (for Circuit #getAlias()#) which creates a circular dependency." />
272 </cfif>
273 <cfset seen[c] = true />
274 <cfif not structKeyExists(variables.fuseboxApplication.circuits,c)>
275 <cfthrow type="fusebox.undefinedCircuit"
276 message="undefined Circuit"
277 detail="You specified a parent Circuit of #c# (for Circuit #getAlias()#) which is not defined." />
278 </cfif>
279 <cfset arrayAppend(this.circuitTrace,c) />
280 <cfset c = variables.fuseboxApplication.circuits[c].getParentName() />
281 </cfloop>
282
283 </cffunction>
284
285 <cffunction name="getOriginalPath" returntype="string" access="public" output="false"
286 hint="I return the original relative path specified in the circuit declaration.">
287
288 <cfreturn variables.originalPath />
289
290 </cffunction>
291
292 <cffunction name="getCircuitRoot" returntype="string" access="public" output="false"
293 hint="I return the full file system path to the circuit directory.">
294
295 <cfreturn variables.fullPath />
296
297 </cffunction>
298
299 <cffunction name="getCircuitXMLFilename" returntype="string" access="public" output="false"
300 hint="I return the actual name of the circuit XML file: circuit.xml or circuit.xml.cfm.">
301
302 <cfreturn variables.circuitFile />
303
304 </cffunction>
305
306 <cffunction name="getOriginalPathIsRelative" returntype="string" access="public" output="false"
307 hint="I return true if this circuit's declaration used a relative path.">
308
309 <cfreturn variables.relative />
310
311 </cffunction>
312
313 <cffunction name="getParentName" returntype="string" access="public" output="false"
314 hint="I return the name (alias) of this circuit's parent.">
315
316 <cfreturn this.parent />
317
318 </cffunction>
319
320 <cffunction name="hasParent" returntype="boolean" access="public" output="false"
321 hint="I return true if this circuit has a parent, otherwise I return false.">
322
323 <cfreturn getParentName() is not "" />
324
325 </cffunction>
326
327 <cffunction name="getParent" returntype="any" access="public" output="false"
328 hint="I return this circuit's parent circuit object. I throw an exception if hasParent() returns false.">
329
330 <!---
331 note that this will throw an exception if the circuit has no parent
332 code should call hasParent() first
333 --->
334 <cfreturn variables.fuseboxApplication.circuits[getParentName()] />
335
336 </cffunction>
337
338 <cffunction name="getPermissions" returntype="string" access="public" output="false"
339 hint="I return the aggregated permissions for this circuit.">
340 <cfargument name="useCircuitTrace" type="boolean" default="false"
341 hint="I indicate whether or not to inherit the parent circuit's permissions if this circuit has no permissions specified." />
342
343 <cfif this.permissions is "" and arguments.useCircuitTrace and hasParent()>
344 <cfreturn getParent().getPermissions(arguments.useCircuitTrace) />
345 <cfelse>
346 <cfreturn this.permissions />
347 </cfif>
348
349 </cffunction>
350
351 <cffunction name="getRelativePath" returntype="string" access="public" output="false"
352 hint="I return the normalized relative path from the application root to this circuit's directory.">
353
354 <cfreturn variables.relativePath />
355
356 </cffunction>
357
358 <cffunction name="getFuseactions" returntype="struct" access="public" output="false"
359 hint="I return the structure containing the definitions of the fuseactions within this circuit.">
360
361 <cfreturn this.fuseactions />
362
363 </cffunction>
364
365 <cffunction name="getLexiconDefinition" returntype="any" access="public" output="false"
366 hint="I return the definition of the specified lexicon.">
367 <cfargument name="namespace" type="any" required="false"
368 hint="I am the namespace whose lexicon is to be retrieved. I am required but it's faster to specify that I am not required." />
369
370 <cfif arguments.namespace is variables.fuseboxLexicon.namespace>
371 <cfreturn variables.fuseboxLexicon />
372 <cfelse>
373 <cfreturn variables.lexicons[arguments.namespace] />
374 </cfif>
375
376 </cffunction>
377
378 <cffunction name="getAccess" returntype="any" access="public" output="false"
379 hint="I return the access specified for this circuit.">
380
381 <cfreturn this.access />
382
383 </cffunction>
384
385 <cffunction name="getAlias" returntype="any" access="public" output="false"
386 hint="I return the circuit alias.">
387
388 <cfreturn variables.alias />
389
390 </cffunction>
391
392 <cffunction name="getApplication" returntype="any" access="public" output="false"
393 hint="I return the fusebox application object.">
394
395 <cfreturn variables.fuseboxApplication />
396
397 </cffunction>
398
399 <cffunction name="getCustomAttributes" returntype="struct" access="public" output="false"
400 hint="I return any custom attributes for the specified namespace prefix.">
401 <cfargument name="ns" type="string" required="true"
402 hint="I am the namespace for which to return custom attributes." />
403
404 <cfif structKeyExists(variables.customAttributes,arguments.ns)>
405 <!--- we structCopy() this so folks can't poke values back into the metadata! --->
406 <cfreturn structCopy(variables.customAttributes[arguments.ns]) />
407 <cfelse>
408 <cfreturn structNew() />
409 </cfif>
410
411 </cffunction>
412
413 <cffunction name="loadLexicons" returntype="void" access="private" output="false"
414 hint="I load the lexicon definitions and custom attributes out of the namespace declarations in the circuit tag.">
415 <cfargument name="circuitCode" type="any" required="true"
416 hint="I am the XML representation of the circuit file." />
417
418 <cfset var attributes = circuitCode.xmlRoot.xmlAttributes />
419 <cfset var attr = "" />
420 <cfset var aLex = "" />
421 <cfset var ns = "" />
422 <cfset var strict = variables.fuseboxApplication.strictMode />
423
424 <!--- pass 1: pull out any namespace declarations --->
425 <cfloop collection="#attributes#" item="attr">
426 <cfif len(attr) gt 6 and left(attr,6) is "xmlns:">
427 <!--- found a namespace declaration, pull it out: --->
428 <cfset aLex = structNew() />
429 <cfset aLex.namespace = listLast(attr,":") />
430 <cfif aLex.namespace is variables.fuseboxLexicon.namespace>
431 <cfthrow type="fusebox.badGrammar.reservedName"
432 message="Attempt to use reserved namespace"
433 detail="You have attempted to declare a namespace '#aLex.namespace#' (in Circuit #getAlias()#) which is reserved by the Fusebox framework." />
434 </cfif>
435 <cfset attributes[attr] = variables.fuseboxApplication.normalizePartialPath(attributes[attr]) />
436 <cfif left(attributes[attr],1) is "/">
437 <!--- assume mapped / root-relative path --->
438 <cfset aLex.path = attributes[attr] />
439 <cfelseif left(variables.fuseboxApplication.lexiconPath,1) is "/">
440 <!--- assume mapped / root-relative path --->
441 <cfset aLex.path = variables.fuseboxApplication.lexiconPath & attributes[attr] />
442 <cfelse>
443 <!--- relative paths --->
444 <cfset aLex.path = variables.fuseboxApplication.getCoreToAppRootPath() &
445 variables.fuseboxApplication.lexiconPath & attributes[attr] />
446 </cfif>
447 <cfset variables.lexicons[aLex.namespace] = aLex />
448 <cfset variables.customAttributes[aLex.namespace] = structNew() />
449 </cfif>
450 </cfloop>
451
452 <!--- pass 2: pull out any custom attributes --->
453 <cfloop collection="#attributes#" item="attr">
454 <cfif listLen(attr,":") eq 2>
455 <!--- looks like a custom attribute: --->
456 <cfset ns = listFirst(attr,":") />
457 <cfif ns is "xmlns">
458 <!--- special case - need to ignore xmlns:foo="bar" --->
459 <cfelseif structKeyExists(variables.customAttributes,ns)>
460 <cfset variables.customAttributes[ns][listLast(attr,":")] = attributes[attr] />
461 <cfelse>
462 <cfthrow type="fusebox.badGrammar.undeclaredNamespace"
463 message="Undeclared lexicon namespace"
464 detail="The lexicon prefix '#ns#' was found on a custom attribute in the <circuit> tag of Circuit #getAlias()# but no such lexicon namespace has been declared." />
465 </cfif>
466 <cfelseif strict and listFind("access,permissions",attr) eq 0>
467 <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
468 message="Unexpected attributes"
469 detail="Unexpected attributes were found in the 'circuit' tag of the '#getAlias()#' circuit.xml file." />
470 </cfif>
471 </cfloop>
472
473 </cffunction>
474
475 <cffunction name="loadPreAndPostFuseactions" returntype="void" access="private" output="false"
476 hint="I load the prefuseaction and postfuseaction definitions from the circuit file.">
477 <cfargument name="circuitCode" type="any" required="true"
478 hint="I am the XML representation of the circuit file." />
479
480 <cfset variables.hasAction = structNew() />
481 <cfset variables.action = structNew() />
482 <cfset variables.callsuper = structNew() />
483 <cfset loadPrePostFuseaction(arguments.circuitCode,"pre") />
484 <cfset loadPrePostFuseaction(arguments.circuitCode,"post") />
485
486 </cffunction>
487
488 <cffunction name="loadPrePostFuseaction" returntype="void" access="private" output="false"
489 hint="I load the either a prefuseaction or a postfuseaction definition from the circuit file.">
490 <cfargument name="circuitCode" type="any" required="true"
491 hint="I am the XML representation of the circuit file." />
492 <cfargument name="prePost" type="string" required="true"
493 hint="I specify whether to load a 'pre'fuseaction or a 'post'fuseaction." />
494
495 <cfset var children = xmlSearch(arguments.circuitCode,"/circuit/#arguments.prePost#fuseaction") />
496 <cfset var i = 0 />
497 <cfset var n = arrayLen(children) />
498 <cfset var nAttrs = 0 />
499
500 <cfif n eq 0>
501 <cfset variables.hasAction[arguments.prePost] = false />
502 <cfelseif n eq 1>
503 <cfset variables.hasAction[arguments.prePost] = true />
504 <cfif structKeyExists(children[1].xmlAttributes,"callsuper")>
505 <cfif listFind("true,false,yes,no",children[1].xmlAttributes.callsuper) eq 0>
506 <cfthrow type="fusebox.badGrammar.invalidAttributeValue"
507 message="Attribute has invalid value"
508 detail="The attribute 'callsuper' must either be ""true"" or ""false"", for a '#arguments.prePost#fuseaction' in Circuit #getAlias()#." />
509 </cfif>
510 <cfset nAttrs = 1 />
511 <cfset variables.callsuper[arguments.prePost] = children[1].xmlAttributes.callsuper />
512 <cfelse>
513 <cfset variables.callsuper[arguments.prePost] = false />
514 </cfif>
515 <cfif variables.fuseboxApplication.strictMode and structCount(children[1].xmlAttributes) neq nAttrs>
516 <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
517 message="Unexpected attributes"
518 detail="Unexpected attributes found on '#arguments.prePost#fuseaction' in Circuit #getAlias()#." />
519 </cfif>
520 <cfset variables.action[arguments.prePost] =
521 createObject("component","fuseboxAction")
522 .init(this,
523 "$#arguments.prePost#fuseaction",
524 "internal",
525 children[1].xmlChildren) />
526 <cfelse>
527 <cfthrow type="fusebox.badGrammar.nonUniqueDeclaration"
528 message="Declaration was not unique"
529 detail="More than one <#arguments.prePost#fuseaction> declaration was found in Circuit #getAlias()#." />
530 </cfif>
531
532 </cffunction>
533
534 <cffunction name="loadFuseactions" returntype="void" access="private" output="false"
535 hint="I load all of the fuseaction definitions from the circuit file.">
536 <cfargument name="circuitCode" type="any" required="true"
537 hint="I am the XML representation of the circuit file." />
538
539 <cfset var children = xmlSearch(arguments.circuitCode,"/circuit/fuseaction") />
540 <cfset var i = 0 />
541 <cfset var n = arrayLen(children) />
542 <cfset var attribs = 0 />
543 <cfset var attr = "" />
544 <cfset var ns = "" />
545 <cfset var customAttribs = 0 />
546 <cfset var access = "" />
547 <cfset var permissions = "" />
548 <cfset var strict = variables.fuseboxApplication.strictMode />
549
550 <cfset this.fuseactions = structNew() />
551 <cfloop from="1" to="#n#" index="i">
552 <!--- default fuseaction access to circuit access --->
553 <cfset access = this.access />
554 <!--- default fuseaction permissions to empty string --->
555 <cfset permissions = "" />
556 <cfset attribs = children[i].xmlAttributes />
557
558 <cfif not structKeyExists(attribs,"name")>
559 <cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
560 message="Required attribute is missing"
561 detail="The attribute 'name' is required, for a 'fuseaction' declaration in circuit #getAlias()#." />
562 </cfif>
563
564 <!--- scan for custom attributes --->
565 <cfset customAttribs = structNew() />
566 <cfloop collection="#attribs#" item="attr">
567
568 <cfswitch expression="#attr#">
569 <cfcase value="name">
570 <cfif structKeyExists(this.fuseactions,attribs.name)>
571 <cfthrow type="fusebox.overloadedFuseaction"
572 message="overloaded Fuseaction"
573 detail="You referenced a fuseaction, #attribs.name#, which has been defined multiple times in circuit #getAlias()#. Fusebox does not allow overloaded methods." />
574 </cfif>
575 </cfcase>
576 <cfcase value="access">
577 <cfset access = attribs.access />
578 <cfif listFind("private,internal,public",access) eq 0>
579 <cfthrow type="fusebox.badGrammar.illegalAccess"
580 message="Fuseaction access illegal"
581 detail="The 'access' value '#access#' is illegal on Fuseaction #attribs.name# in Circuit #getAlias()#. 'private', 'internal' or 'public' are the only legal values." />
582 </cfif>
583 </cfcase>
584 <cfcase value="permissions">
585 <cfset permissions = attribs.permissions />
586 </cfcase>
587 <cfdefaultcase>
588 <cfif listLen(attr,":") eq 2>
589 <!--- looks like a custom attribute: --->
590 <cfset ns = listFirst(attr,":") />
591 <cfif structKeyExists(variables.customAttributes,ns)>
592 <cfset customAttribs[ns][listLast(attr,":")] = attribs[attr] />
593 <cfelse>
594 <cfthrow type="fusebox.badGrammar.undeclaredNamespace"
595 message="Undeclared lexicon namespace"
596 detail="The lexicon prefix '#ns#' was found on a custom attribute in the Fuseaction #attribs.name# in Circuit #getAlias()# but no such lexicon namespace has been declared." />
597 </cfif>
598
599 <cfelseif strict>
600 <cfthrow type="fusebox.badGrammar.unexpectedAttributes"
601 message="Unexpected attributes"
602 detail="Unexpected attribute '#attr#' found on Fuseaction #attribs.name# in Circuit #getAlias()#." />
603 </cfif>
604 </cfdefaultcase>
605 </cfswitch>
606 </cfloop>
607
608 <cfset this.fuseactions[attribs.name] =
609 createObject("component","fuseboxAction")
610 .init(this,attribs.name,access,children[i].xmlChildren,false,customAttribs) />
611 <!--- FB41 security plugin compatibility: --->
612 <cfset this.fuseactions[attribs.name].permissions = permissions />
613 </cfloop>
614
615 </cffunction>
616
617</cfcomponent>