/core/factory.cfc

http://github.com/atuttle/Taffy · ColdFusion CFScript · 202 lines · 194 code · 5 blank · 3 comment · 8 complexity · 8c44ed69fd11aca845948cb42a0009f0 MD5 · raw file

  1. <cfcomponent output="false">
  2. <cfscript>
  3. //bean cache
  4. this.beans = structNew();
  5. this.transients = structNew();
  6. //functionality
  7. </cfscript>
  8. <cffunction name="init" output="false">
  9. <cfargument name="externalBeanFactory">
  10. <cfscript>
  11. if (structKeyExists(arguments, "externalBeanFactory")) {
  12. this.externalBeanFactory = arguments.externalBeanFactory;
  13. }
  14. return this;
  15. </cfscript>
  16. </cffunction>
  17. <cfscript>
  18. // Proxy to beanExists to provide similar interface to ColdSpring
  19. function containsBean(beanName){
  20. return beanExists(arguments.beanName);
  21. }
  22. function transientExists(beanName){
  23. return structKeyExists(this.transients, arguments.beanName);
  24. }
  25. function getBean(beanName){
  26. var b = 0;
  27. var meta = 0;
  28. if (beanExists(arguments.beanName, false, false)){
  29. return this.beans[arguments.beanName];
  30. }else if (transientExists(arguments.beanName)){
  31. b = createObject('component', this.transients[arguments.beanName]);
  32. meta = getMetadata(b);
  33. _recurse_ResolveDependencies(b, meta);
  34. return b;
  35. }else if (externalBeanExists(arguments.beanName)){
  36. return this.externalBeanFactory.getBean(arguments.beanName);
  37. }else{
  38. throwError(message="Bean name '#arguments.beanName#' not found.", type="Taffy.Factory.BeanNotFound");
  39. }
  40. }
  41. function getBeanList(){
  42. var combined = structKeyList(this.beans);
  43. var trans = structKeyList(this.transients);
  44. if (len(combined) and len(trans)){
  45. combined = combined & ",";
  46. }
  47. combined = combined & trans;
  48. return combined;
  49. }
  50. </cfscript>
  51. <cffunction name="beanExists" output="false">
  52. <cfargument required="true" name="beanName">
  53. <cfargument name="includeTransients" default="true">
  54. <cfargument name="includeExternal" default="false">
  55. <cfscript>
  56. return structKeyExists(this.beans, arguments.beanName) or (arguments.includeTransients and transientExists(arguments.beanName)) or
  57. (arguments.includeExternal and externalBeanExists(arguments.beanName));
  58. </cfscript>
  59. </cffunction>
  60. <cffunction name="externalBeanExists" access="private" output="false" returnType="boolean">
  61. <cfargument required="true" name="beanName">
  62. <cfscript>
  63. return structKeyExists(this, "externalBeanFactory") and this.externalBeanFactory.containsBean(arguments.beanName);
  64. </cfscript>
  65. </cffunction>
  66. <cffunction name="loadBeansFromPath" access="public" output="false" returnType="void">
  67. <cfargument name="beanPath" type="string" required="true" hint="Absolute path to folder containing beans" />
  68. <cfargument name="resourcesPath" type="string" default="resources" />
  69. <cfargument name="resourcesBasePath" type="string" default="" />
  70. <cfargument name="isFullReload" type="boolean" default="false" />
  71. <cfargument name="taffyRef" type="any" required="false" default="#structNew()#" />
  72. <cfset var local = StructNew() />
  73. <!--- cache all of the beans --->
  74. <cfif isFullReload>
  75. <cfset this.beans = structNew() />
  76. <cfset arguments.taffyRef.status.skippedResources = arrayNew(1) /> <!--- empty out the array on factory reloads --->
  77. <cfset arguments.taffyRef.beanList = "" />
  78. </cfif>
  79. <!--- if the folder doesn't exist, do nothing --->
  80. <cfif not directoryExists(arguments.beanPath)>
  81. <cfreturn />
  82. </cfif>
  83. <!--- get list of beans to load --->
  84. <cfdirectory action="list" directory="#arguments.beanPath#" filter="*.cfc" name="local.beanQuery" recurse="true" />
  85. <cfloop query="local.beanQuery">
  86. <cfset local.beanName = filePathToBeanName(local.beanQuery.directory, local.beanquery.name, arguments.resourcesBasePath) />
  87. <cfset local.beanPath = filePathToBeanPath(local.beanQuery.directory, local.beanquery.name, arguments.resourcesPath, arguments.resourcesBasePath) />
  88. <cftry>
  89. <cfset local.objBean = createObject("component", local.beanPath) />
  90. <cfif isInstanceOf(local.objBean, "taffy.core.baseSerializer")>
  91. <cfset this.transients[local.beanName] = local.beanPath />
  92. <cfelse>
  93. <cfset this.beans[local.beanName] = local.objBean />
  94. </cfif>
  95. <cfcatch>
  96. <!--- skip cfc's with errors, but save info about them for display in the dashboard --->
  97. <cfset local.err = structNew() />
  98. <cfset local.err.resource = local.beanName />
  99. <cfset local.err.exception = cfcatch />
  100. <cfset arrayAppend(arguments.taffyRef.status.skippedResources, local.err) />
  101. </cfcatch>
  102. </cftry>
  103. </cfloop>
  104. <!--- resolve dependencies --->
  105. <cfloop list="#structKeyList(this.beans)#" index="local.b">
  106. <cfset local.bean = this.beans[local.b] />
  107. <cfset local.beanMeta = getMetadata(local.bean) />
  108. <cfset _recurse_ResolveDependencies(local.bean, local.beanMeta) />
  109. </cfloop>
  110. </cffunction>
  111. <cffunction name="filePathToBeanPath" access="private">
  112. <cfargument name="path" />
  113. <cfargument name="filename" />
  114. <cfargument name="resourcesPath" />
  115. <cfargument name="resourcesBasePath" />
  116. <cfset var beanPath = "" />
  117. <cfif len(resourcesBasePath) eq 0>
  118. <cfset arguments.resourcesBasePath = "!@$%^&*()" />
  119. </cfif>
  120. <cfset beanPath =
  121. resourcesPath
  122. &
  123. "."
  124. &
  125. replaceList(
  126. replace(path, resourcesBasePath, ""),
  127. "/,\",
  128. ".,."
  129. )
  130. &
  131. "."
  132. &
  133. replace(
  134. filename,
  135. ".cfc",
  136. ""
  137. )
  138. />
  139. <cfset beanPath = replace(beanPath, "..", ".", "ALL") />
  140. <cfif left(beanPath, 1) eq ".">
  141. <cfset beanPath = right(beanPath, len(beanPath)-1) />
  142. </cfif>
  143. <cfreturn beanPath />
  144. </cffunction>
  145. <cffunction name="filePathToBeanName" access="private">
  146. <cfargument name="path" />
  147. <cfargument name="filename" />
  148. <cfargument name="basepath" />
  149. <cfif len(basepath) eq 0>
  150. <cfset arguments.basePath = "!@$%^&*()" />
  151. </cfif>
  152. <cfreturn
  153. replaceList(
  154. replace(path, basepath, ""),
  155. "/,\",
  156. ","
  157. )
  158. & replace(
  159. filename,
  160. ".cfc",
  161. ""
  162. )
  163. />
  164. </cffunction>
  165. <cffunction name="_recurse_ResolveDependencies" access="private">
  166. <cfargument name="bean" required="true" />
  167. <cfargument name="metaData" type="struct" required="true" />
  168. <cfset var local = structNew() />
  169. <cfif structKeyExists(arguments.metaData, "functions") and isArray(arguments.metaData.functions)>
  170. <cfloop from="1" to="#arrayLen(arguments.metaData.functions)#" index="local.f">
  171. <cfset local.fname = arguments.metaData.functions[local.f].name />
  172. <cfif len(local.fname) gt 3>
  173. <cfset local.propName = right(local.fname, len(local.fname)-3) />
  174. <cfif left(local.fname, 3) eq "set" and beanExists(local.propName, true, true)>
  175. <cfset evaluate("arguments.bean.#local.fname#(getBean('#local.propName#'))") />
  176. </cfif>
  177. </cfif>
  178. </cfloop>
  179. </cfif>
  180. <cfif structKeyExists(arguments.metaData, "properties") and isArray(arguments.metaData.properties)>
  181. <cfloop from="1" to="#arrayLen(arguments.metaData.properties)#" index="local.p">
  182. <cfset local.propName = arguments.metaData.properties[local.p].name />
  183. <cfif beanExists(local.propName, true, true)>
  184. <cfset arguments.bean[local.propName] = getBean(local.propName) />
  185. </cfif>
  186. </cfloop>
  187. </cfif>
  188. <cfif structKeyExists(arguments.metaData, "extends") and isStruct(arguments.metaData.extends)>
  189. <cfset _recurse_ResolveDependencies(arguments.bean, arguments.metaData.extends) />
  190. </cfif>
  191. </cffunction>
  192. <!--- proxy function for CF8 compatibility --->
  193. <cffunction name="throwError">
  194. <cfthrow attributecollection="#arguments#" />
  195. </cffunction>
  196. </cfcomponent>