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 output="false" hint="I represent a plugin declaration.">
    17
    18	<cffunction name="init" returntype="fuseboxPlugin" access="public" output="false" 
    19				hint="I am the constructor.">
    20		<cfargument name="phase" type="string" required="true" 
    21					hint="I am the phase with which this plugin is associated." />
    22		<cfargument name="pluginXML" type="any" required="true" 
    23					hint="I am the XML representation of this plugin's declaration." />
    24		<cfargument name="fbApp" type="fuseboxApplication" required="true" 
    25					hint="I am the fusebox application object." />
    26		<cfargument name="lexicons" type="struct" required="true" 
    27					hint="I am the lexicons declared in the fusebox.xml file that are available as custom attributes." />
    28	
    29		<cfset var i = 0 />
    30		<cfset var n = arrayLen(arguments.pluginXML.xmlChildren) />
    31		<cfset var attr = 0 />
    32		<cfset var ns = "" />
    33		<cfset var verbChildren = arrayNew(1) />
    34		<cfset var factory = arguments.fbApp.getFuseactionFactory() />
    35		<cfset var ext = "." & arguments.fbApp.scriptFileDelimiter />
    36		
    37		<cfif arguments.pluginXML.xmlName is "plugin">
    38		
    39			<cfif not structKeyExists(arguments.pluginXML.xmlAttributes,"name")>
    40				<cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
    41						message="Required attribute is missing"
    42						detail="The attribute 'name' is required, for a '#arguments.phase#' plugin declaration in fusebox.xml." />
    43			</cfif>
    44			
    45			<cfset variables.name = arguments.pluginXML.xmlAttributes.name />
    46			<cfset variables.fuseboxApplication = arguments.fbApp />
    47			<cfset variables.customAttribs = structNew() />
    48	
    49			<cfif not structKeyExists(arguments.pluginXML.xmlAttributes,"template")>
    50				<cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
    51						message="Required attribute is missing"
    52						detail="The attribute 'template' is required, for the '#getName()#' plugin declaration in fusebox.xml." />
    53			</cfif>
    54	
    55			<cfset variables.phase = arguments.phase />
    56
    57			<cfset this.path = arguments.fbApp.getPluginsPath() />
    58
    59			<cfif structKeyExists(arguments.pluginXML.xmlAttributes,"path")>
    60				<cfif left(arguments.pluginXML.xmlAttributes.path,1) is "/">
    61					<!--- path is absolute, ignore normal plugins path --->
    62					<cfset this.path = arguments.fbApp.normalizePartialPath(arguments.pluginXML.xmlAttributes.path) />
    63				<cfelse>
    64					<cfset this.path = this.path & arguments.fbApp.normalizePartialPath(arguments.pluginXML.xmlAttributes.path) />
    65				</cfif>
    66			</cfif>
    67			
    68			<!--- look for any valid custom attributes --->
    69			<cfloop collection="#arguments.pluginXML.xmlAttributes#" item="attr">
    70				<cfswitch expression="#attr#">
    71
    72				<cfcase value="name,template,path">
    73					<!--- already processed --->
    74				</cfcase>
    75
    76				<cfdefaultcase>
    77
    78					<cfif listLen(attr,":") eq 2>
    79						<!--- looks like a custom attribute: --->
    80						<cfset ns = listFirst(attr,":") />
    81						<cfif structKeyExists(arguments.lexicons,ns)>
    82							<cfset customAttribs[ns][listLast(attr,":")] = arguments.pluginXML.xmlAttributes[attr] />
    83						<cfelse>
    84							<cfthrow type="fusebox.badGrammar.undeclaredNamespace" 
    85									message="Undeclared lexicon namespace" 
    86									detail="The lexicon prefix '#ns#' was found on a custom attribute in the '#getName()#' plugin declaration in fusebox.xml but no such lexicon namespace has been declared." />
    87						</cfif>
    88	
    89					<cfelseif arguments.fbApp.strictMode>
    90						<cfthrow type="fusebox.badGrammar.unexpectedAttributes"
    91								message="Unexpected attributes"
    92								detail="Unexpected attribute '#attr#' found in the '#getName()#' plugin declaration in fusebox.xml." />
    93					</cfif>
    94					
    95				</cfdefaultcase>
    96
    97				</cfswitch>
    98			</cfloop>
    99			
   100			<cfset variables.template = arguments.pluginXML.xmlAttributes.template />
   101			<cfif len(variables.template) lt 4 or right(variables.template,4) is not ext>
   102				<cfset variables.template = variables.template & ext />
   103			</cfif>
   104			<cfif left(this.path,1) is "/">
   105				<cfset this.rootpath =
   106						arguments.fbApp.relativePath(arguments.fbApp.expandFuseboxPath(this.path),arguments.fbApp.getApplicationRoot()) />
   107			<cfelse>
   108				<cfset this.rootpath =
   109						arguments.fbApp.relativePath(arguments.fbApp.getApplicationRoot() &
   110														this.path,arguments.fbApp.getApplicationRoot()) />
   111			</cfif>
   112			
   113			<cfset this.rootpath = arguments.fbApp.getCanonicalPath(this.rootpath) />
   114			
   115			<cfset variables.parameters = arguments.pluginXML.xmlChildren />
   116			<cfset variables.paramVerbs = structNew() />
   117			<cfloop from="1" to="#n#" index="i">
   118				
   119				<cfif variables.parameters[i].xmlName is not "parameter">
   120					<cfthrow type="fusebox.badGrammar.illegalDeclaration"
   121							message="Parameter expected in plugin declaration"
   122							detail="A 'plugin' declaration contained '#variables.parameters[i].xmlName#' but only 'parameter' is allowed, in fusebox.xml." />
   123				</cfif>
   124				<cfif not structKeyExists(variables.parameters[i].xmlAttributes,"name")>
   125					<cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
   126							message="Required attribute is missing"
   127							detail="The attribute 'name' is required, for a 'parameter' to the '#getName()#' plugin declaration in fusebox.xml." />
   128				</cfif>
   129
   130				<cfif not structKeyExists(variables.parameters[i].xmlAttributes,"value")>
   131					<cfthrow type="fusebox.badGrammar.requiredAttributeMissing"
   132							message="Required attribute is missing"
   133							detail="The attribute 'value' is required, for a 'parameter' to the '#getName()#' plugin declaration in fusebox.xml." />
   134				</cfif>
   135
   136				<cfif arguments.fbApp.strictMode and structCount(variables.parameters[i].xmlAttributes) neq 2>
   137					<cfthrow type="fusebox.badGrammar.unexpectedAttributes"
   138							message="Unexpected attributes"
   139							detail="Unexpected attributes were found in the '#variables.parameters[i].xmlAttributes.name#' parameter of the '#getName()#' plugin declaration in fusebox.xml." />
   140				</cfif>
   141
   142				<cfset attr = structNew() />
   143				<cfset attr.name = "myFusebox.plugins.#getName()#.parameters." & variables.parameters[i].xmlAttributes.name />
   144				<cfset attr.value = variables.parameters[i].xmlAttributes.value />
   145				<cfset variables.paramVerbs[i] = factory.create("set",this,attr,verbChildren) />
   146
   147			</cfloop>
   148		<cfelse>
   149			<cfthrow type="fusebox.badGrammar.illegalDeclaration" 
   150					message="Illegal declaration" 
   151					detail="The XML entity '#arguments.pluginXML.xmlName#' was found where a plugin declaration was expected in fusebox.xml." />
   152		</cfif>
   153	
   154		<cfreturn this />
   155		
   156	</cffunction>
   157	
   158	<cffunction name="compile" returntype="void" access="public" output="false" 
   159				hint="I compile this plugin object.">
   160		<cfargument name="writer" type="any" required="false" 
   161					hint="I am the parsed file writer object. I am required but it's faster to specify that I am not required." />
   162		
   163		<cfset var i = 0 />
   164		<cfset var n = structCount(variables.paramVerbs) />
   165		<cfset var file = "" />
   166		<cfset var p = "" />
   167		
   168		<cfif request.__fusebox.SuppressPlugins>
   169			<cfreturn />
   170		</cfif>
   171		<cfswitch expression="#variables.phase#">
   172		<cfcase value="processError,fuseactionException">
   173			<cfif left(this.path,1) is "/">
   174				<cffile action="read" file="#variables.fuseboxApplication.expandFuseboxPath(this.path)##variables.template#"
   175						variable="file"
   176						charset="#variables.fuseboxApplication.characterEncoding#" />
   177			<cfelse>
   178				<cffile action="read" file="#variables.fuseboxApplication.getApplicationRoot()##this.path##variables.template#"
   179						variable="file"
   180						charset="#variables.fuseboxApplication.characterEncoding#" />
   181			</cfif>
   182			<cfset arguments.writer.rawPrintln(file) />
   183		</cfcase>
   184		<cfdefaultcase>
   185			<cfloop from="1" to="#n#" index="i">
   186				<cfset variables.paramVerbs[i].compile(arguments.writer) />
   187			</cfloop>
   188			<cfset p = arguments.writer.setPhase(variables.phase) />
   189			<cfset arguments.writer.println('<cfset myFusebox.thisPlugin = "#getName()#"/>') />
   190			<cfset arguments.writer.print('<' & 'cfoutput><' & 'cfinclude template=') />
   191			<cfif left(this.path,1) is "/">
   192				<cfset arguments.writer.print('"#this.path##variables.template#"') />
   193			<cfelse>
   194				<cfset arguments.writer.print('"#variables.fuseboxApplication.parseRootPath##this.path##variables.template#"') />
   195			</cfif>
   196			<cfset arguments.writer.println('/><' & '/cfoutput>') />
   197			<cfset arguments.writer.setPhase(p) />
   198		</cfdefaultcase>
   199		</cfswitch>
   200
   201	</cffunction>
   202	
   203	<cffunction name="getName" returntype="string" access="public" output="false" 
   204				hint="I return the name of the plugin.">
   205		
   206		<cfreturn variables.name />
   207		
   208	</cffunction>
   209
   210	<cffunction name="getCircuit" returntype="any" access="public" output="false" 
   211				hint="I return the enclosing application object. This is an edge case to allow code that works with fuseactions to work with plugins too.">
   212	
   213		<cfreturn variables.fuseboxApplication />
   214	
   215	</cffunction>
   216	
   217	<cffunction name="getCustomAttributes" returntype="struct" access="public" output="false" 
   218				hint="I return the custom (namespace-qualified) attributes for this plugin tag.">
   219		<cfargument name="ns" type="string" required="true" 
   220					hint="I am the namespace prefix whose attributes should be returned." />
   221		
   222		<cfif structKeyExists(variables.customAttribs,arguments.ns)>
   223			<!--- we structCopy() this so folks can't poke values back into the metadata! --->
   224			<cfreturn structCopy(variables.customAttribs[arguments.ns]) />
   225		<cfelse>
   226			<cfreturn structNew() />
   227		</cfif>
   228		
   229	</cffunction>
   230	
   231</cfcomponent>