Sorcerer's IsleCode QueryParam Scanner / files

  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 hint="I represent an implicit circuit." output="false">
 17	
 18	<cffunction name="init" returntype="any" 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="myFusebox" type="myFusebox" required="true" 
 25					hint="I am the myFusebox data structure." />
 26
 27		<cfset var traditionalCircuit = false />
 28		<cfset var circuitPrefix = "" />
 29		<cfset var circuitSearchPath =
 30					"controller/#arguments.alias#,model/#arguments.alias#,view/#arguments.alias#," &
 31					"#arguments.alias#/controller,#arguments.alias#/model,#arguments.alias#/view," &
 32					"#arguments.alias#" />
 33		
 34		<cfset variables.fuseboxApplication = arguments.fbApp />
 35		<cfset variables.alias = arguments.alias />
 36		
 37		<cfset variables.appPath = variables.fuseboxApplication.getApplicationRoot() />
 38		<cfset variables.fuseboxLexicon = variables.fuseboxApplication.getFuseactionFactory().getBuiltinLexicon() />
 39
 40		<!--- ensure we don't reload this in the same request --->
 41		<cfset request.__fusebox.CircuitsLoaded[variables.alias] = true />
 42
 43		<!---
 44			look for traditional circuit in MVC/alias or alias/MVC or just alias directories:
 45		--->
 46		<cfloop index="circuitPrefix" list="#circuitSearchPath#">
 47			<cfset traditionalCircuit =
 48					fileExists(variables.appPath & circuitPrefix & "/circuit.xml.cfm") or
 49					fileExists(variables.appPath & circuitPrefix & "/circuit.xml") />
 50			<cfif traditionalCircuit>
 51				<cfbreak />
 52			</cfif>
 53		</cfloop>
 54		<!---
 55			if we found a traditional circuit that simply wasn't declared,
 56			return a regular Fusebox 5.x style circuit object:
 57		--->
 58		<cfif traditionalCircuit>
 59			<cfif variables.fuseboxApplication.debug>
 60				<cfset arguments.myFusebox.trace("Compiler","Implicit #circuitPrefix#/circuit.xml(.cfm) identified") />
 61			</cfif>
 62			<cfreturn createObject("component","fuseboxCircuit")
 63						.init(variables.fuseboxApplication,
 64								getAlias(),
 65								circuitPrefix,
 66								"",
 67								arguments.myFusebox,
 68								true) />
 69		</cfif>
 70
 71		<!---
 72			now we're off into convention over configuration territory...
 73		--->
 74		<cfset reload(arguments.myFusebox) />
 75			
 76		<cfreturn this />
 77		
 78	</cffunction>
 79	
 80	<cffunction name="reload" returntype="any" access="public" output="false" 
 81				hint="I reload the circuit file and build the in-memory structures from it.">
 82		<cfargument name="myFusebox" type="myFusebox" required="true" 
 83					hint="I am the myFusebox data structure." />
 84
 85		<cfset var found = false />
 86		<cfset var path = "" />
 87		
 88		<cfset this.access = "public" />
 89		<cfset variables.fuseactionIsMethod = false />
 90		
 91		<!---
 92			in order of preference, we want to find:
 93			1. {MVC}/{alias}.cfc
 94				- this implies fuseactions are methods
 95			2. {MVC}/{alias}/
 96				- we can look for {fuseaction}.xml or {fuseaction}.cfm later
 97			3. {alias}/
 98				- we can look for {fuseaction}.xml or {fuseaction}.cfm later
 99		--->
100
101		<cfloop index="path" list="controller/,model/,view/">
102
103			<cfset variables.originalPath = path />
104			<cfset variables.fullPath = variables.appPath & variables.originalPath />
105			<cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
106	
107			<!--- if the CFC actually exists, see if we can figure out if it exists in a sensible place --->
108			<cfif fileExists(variables.fullPath & getAlias() & ".cfc")>
109				<cfset variables.dottedPath = variables.fuseboxApplication.locateCfc(variables.fullPath & getAlias() & ".cfc") />
110				<cfif variables.dottedPath is not "">
111					<cfset found = true />
112					<cfset variables.fuseactionIsMethod = true />
113					<cfif variables.fuseboxApplication.debug>
114						<cfset arguments.myFusebox.trace("Compiler","Implicit component-as-circuit #variables.originalPath##getAlias()#.cfc identified") />
115					</cfif>
116					<cfbreak />
117				</cfif>
118			</cfif>
119
120			<!--- first time through, access is public for controller - should change to internal for model / view circuits --->
121			<cfset this.access = "internal" />
122			
123		</cfloop>
124
125		<cfif not found>
126			<!--- no CFCs so look for an MVC directory --->
127			<cfset this.access = "public" />
128
129			<cfloop index="path" list="controller/,model/,view/">
130	
131				<cfset variables.originalPath = path & getAlias() & "/" />
132				<cfset variables.fullPath = variables.appPath & variables.originalPath />
133				<cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
134	
135				<!--- MVC circuit directory? --->
136				<cfif directoryExists(variables.fullPath)>
137					<!--- looks like we have a candidate --->
138					<cfset found = true />
139					<cfif variables.fuseboxApplication.debug>
140						<cfset arguments.myFusebox.trace("Compiler","Implicit circuit #variables.originalPath# identified") />
141					</cfif>
142					<cfbreak />
143				</cfif>
144				
145				<!--- first time through, access is public for controller - should change to internal for model / view circuits --->
146				<cfset this.access = "internal" />
147				
148			</cfloop>
149
150		</cfif>					
151		
152		<cfif not found>
153			<!--- no MVC, what about just a directory? --->
154			<cfset this.access = "public" />
155			<cfset variables.originalPath = getAlias() & "/" />
156			<cfset variables.fullPath = variables.appPath & variables.originalPath />
157			<cfset variables.relativePath = variables.fuseboxApplication.relativePath(variables.appPath,variables.fullPath) />
158
159			<cfif directoryExists(variables.fullPath)>
160
161				<!--- ok, the directory exists --->
162				<cfif variables.fuseboxApplication.debug>
163					<cfset arguments.myFusebox.trace("Compiler","Implicit circuit #getAlias()# identified") />
164				</cfif>
165
166			<cfelse>
167
168				<cfthrow type="fusebox.undefinedCircuit" 
169						message="undefined Circuit" 
170						detail="You specified a Circuit of #getAlias()# which is not defined." />
171
172			</cfif>
173
174		</cfif>
175		
176		<!--- we don't know what fuseactions an implicit circuit has --->
177		<cfset this.fuseactions = structNew() />
178		<cfset this.parent = "" />
179		<cfset this.permissions = "" />
180		<cfset this.path = variables.relativePath />
181		<cfset this.rootPath = variables.fuseboxApplication.relativePath(variables.fullPath,variables.appPath) />
182		<cfset this.timestamp = now() />
183
184	</cffunction>
185	
186	<cffunction name="compile" returntype="void" access="public" output="false" 
187				hint="I compile a given fuseaction within this circuit.">
188		<cfargument name="writer" type="any" required="false" 
189					hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
190		<cfargument name="fuseaction" type="any" required="false" 
191					hint="I am the name of the fuseaction to compile. I am required but it's faster to specify that I am not required." />
192		<cfargument name="topLevel" type="boolean" default="false" 
193					hint="I specify whether or not this is a top-level (public) request." />
194
195		<cfset var f = arguments.writer.setFuseaction(arguments.fuseaction) />
196		
197		<cfif arguments.fuseaction is "prefuseaction" or arguments.fuseaction is "postfuseaction">
198			<cfthrow type="fusebox.undefinedFuseaction" 
199					message="undefined Fuseaction" 
200					detail="You specified a Fuseaction of #arguments.fuseaction# which is uncallable in Circuit #getAlias()#." />
201		</cfif>
202
203		<!--- prefuseaction is handled internally to the circuit mechanism --->
204
205		<cfif not structKeyExists(this.fuseactions,arguments.fuseaction)>
206			<cfif variables.fuseactionIsMethod>
207				<cfset this.fuseactions[arguments.fuseaction] = 
208							createObject("component","fuseboxControllerMethod")
209								.init(this,variables.dottedPath,arguments.fuseaction,true) />
210			<cfelse>
211				<!--- attempt to find the fuseaction as a file in the circuit directory --->
212				<cfif fileExists(variables.fullPath & arguments.fuseaction & ".xml")>
213					<!--- fuseaction.xml fragment --->
214					<cfthrow type="fusebox.undefinedFuseaction" 
215							message="undefined Fuseaction" 
216							detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
217				<cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfc")>
218					<!--- fuseaction.cfc (call do() on this) --->
219					<cfset variables.dottedPath = getApplication().locateCfc(variables.fullPath & arguments.fuseaction & ".cfc") />
220					<cfif variables.dottedPath is not "">
221						<cfset this.fuseactions[arguments.fuseaction] = 
222									createObject("component","fuseboxControllerMethod")
223										.init(this,variables.dottedPath,arguments.fuseaction,false) />
224					<cfelse>
225						<cfthrow type="fusebox.undefinedFuseaction" 
226								message="undefined Fuseaction" 
227								detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
228					</cfif>
229				<cfelseif fileExists(variables.fullPath & arguments.fuseaction & ".cfm")>
230					<!--- fuseaction.cfm (i.e., a fuse) --->
231					<cfset this.fuseactions[arguments.fuseaction] = 
232								createObject("component","fuseboxImplicitFuseaction")
233									.init(this,arguments.fuseaction) />
234				<cfelse>
235					<cfthrow type="fusebox.undefinedFuseaction" 
236							message="undefined Fuseaction" 
237							detail="You specified a Fuseaction of #arguments.fuseaction# which is not defined in Circuit #getAlias()#." />
238				</cfif>
239			</cfif>
240		</cfif>
241
242		<cfif arguments.topLevel>
243			<cfif this.access is not "public">
244				<cfthrow type="fusebox.invalidAccessModifier" 
245						message="Invalid Access Modifier" 
246						detail="You tried to access #getAlias()#.#arguments.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." />
247			</cfif>
248		</cfif>	
249
250		<cfset this.fuseactions[arguments.fuseaction].compile(arguments.writer) />
251		
252		<!--- postfuseaction is handled internally to the circuit mechanism --->
253
254		<cfset arguments.writer.setFuseaction(f) />
255		
256	</cffunction>
257
258	<cffunction name="compilePreOrPostFuseaction" returntype="void" access="public" output="false" 
259				hint="I compile the pre/post-fuseaction for a circuit.">
260		<cfargument name="writer" type="any" required="false" 
261					hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
262		<cfargument name="preOrPost" type="string" required="false" 
263					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." />
264
265		<!--- implicit circuits do not have pre/post fuseactions so this is a no-op --->
266
267	</cffunction>
268	
269	<cffunction name="buildCircuitTrace" returntype="void" access="public" output="false" 
270				hint="I build the 'circuit trace' structure - the array of parents. Required for Fusebox 4.1 compatibility.">
271
272		<cfset this.circuitTrace = arrayNew(1) />
273		<cfset arrayAppend(this.circuitTrace,getAlias()) />
274		
275	</cffunction>
276	
277	<cffunction name="getOriginalPath" returntype="string" access="public" output="false" 
278				hint="I return the original relative path specified in the circuit declaration.">
279		
280		<cfreturn variables.originalPath />
281		
282	</cffunction>
283	
284	<cffunction name="getCircuitRoot" returntype="string" access="public" output="false" 
285				hint="I return the full file system path to the circuit directory.">
286
287		<cfreturn variables.fullPath />
288		
289	</cffunction>
290	
291	<cffunction name="getCircuitXMLFilename" returntype="string" access="public" output="false" 
292				hint="I return the actual name of the circuit XML file: circuit.xml or circuit.xml.cfm.">
293		
294		<!--- there is no XML file for an implicit circuit --->
295		<cfreturn "" />
296		
297	</cffunction>
298	
299	<cffunction name="getOriginalPathIsRelative" returntype="string" access="public" output="false" 
300				hint="I return true if this circuit's declaration used a relative path.">
301		
302		<!--- original path is relative by definition --->
303		<cfreturn true />
304		
305	</cffunction>
306	
307	<cffunction name="getParentName" returntype="string" access="public" output="false" 
308				hint="I return the name (alias) of this circuit's parent.">
309	
310		<cfreturn this.parent />
311	
312	</cffunction>
313
314	<cffunction name="hasParent" returntype="boolean" access="public" output="false" 
315				hint="I return true if this circuit has a parent, otherwise I return false.">
316	
317		<cfreturn getParentName() is not "" />
318	
319	</cffunction>
320
321	<cffunction name="getParent" returntype="any" access="public" output="false" 
322				hint="I return this circuit's parent circuit object. I throw an exception if hasParent() returns false.">
323	
324		<!---
325			note that this will throw an exception if the circuit has no parent
326			code should call hasParent() first
327		--->
328		<cfreturn variables.fuseboxApplication.circuits[getParentName()] />
329	
330	</cffunction>
331
332	<cffunction name="getPermissions" returntype="string" access="public" output="false" 
333				hint="I return the aggregated permissions for this circuit.">
334		<cfargument name="useCircuitTrace" type="boolean" default="false" 
335					hint="I indicate whether or not to inherit the parent circuit's permissions if this circuit has no permissions specified." />
336
337		<cfreturn this.permissions />
338				
339	</cffunction>
340
341	<cffunction name="getRelativePath" returntype="string" access="public" output="false" 
342				hint="I return the normalized relative path from the application root to this circuit's directory.">
343	
344		<cfreturn variables.relativePath />
345	
346	</cffunction>
347
348	<cffunction name="getFuseactions" returntype="struct" access="public" output="false" 
349				hint="I return the structure containing the definitions of the fuseactions within this circuit.">
350		
351		<cfreturn this.fuseactions /> 
352		
353	</cffunction>
354
355	<cffunction name="getLexiconDefinition" returntype="any" access="public" output="false" 
356				hint="I return the definition of the specified lexicon.">
357		<cfargument name="namespace" type="any" required="false" 
358					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." />
359		
360		<cfif arguments.namespace is variables.fuseboxLexicon.namespace>
361			<cfreturn variables.fuseboxLexicon />
362		<!--- else we return nothing because this is an illegal call --->
363		</cfif>
364
365	</cffunction>
366
367	<cffunction name="getAccess" returntype="any" access="public" output="false" 
368				hint="I return the access specified for this circuit.">
369	
370		<cfreturn this.access />
371	
372	</cffunction>
373	
374	<cffunction name="getAlias" returntype="any" access="public" output="false" 
375				hint="I return the circuit alias.">
376	
377		<cfreturn variables.alias />
378	
379	</cffunction>
380
381	<cffunction name="getApplication" returntype="any" access="public" output="false" 
382				hint="I return the fusebox application object.">
383	
384		<cfreturn variables.fuseboxApplication />
385	
386	</cffunction>
387
388	<cffunction name="getCustomAttributes" returntype="struct" access="public" output="false" 
389				hint="I return any custom attributes for the specified namespace prefix.">
390		<cfargument name="ns" type="string" required="true" 
391					hint="I am the namespace for which to return custom attributes." />
392		
393		<!--- implicit circuits have no custom attributes --->
394		<cfreturn structNew() />
395
396	</cffunction>
397
398</cfcomponent>