/cacheManagement/io/javaloader/JavaProxy.cfc

http://coldfusioncachemanager.googlecode.com/ · ColdFusion CFScript · 354 lines · 281 code · 70 blank · 3 comment · 33 complexity · 66a573229c5878306e37ab05c60af0fd MD5 · raw file

  1. <!--- Document Information -----------------------------------------------------
  2. Title: JavaProxy.cfc
  3. Author: Mark Mandel
  4. Email: mark@compoundtheory.com
  5. Website: http://www.compoundtheory.com
  6. Purpose: JavaProxy to replace the ColdFusion one when you don't have access
  7. to coldfusion.* packages due to CF8 settings.
  8. Usage:
  9. Modification Log:
  10. Name Date Description
  11. ================================================================================
  12. Mark Mandel 27/08/2007 Created
  13. ------------------------------------------------------------------------------->
  14. <cfcomponent output="false">
  15. <!---
  16. All CF based methods have a _ in front, so that they don't interfere with the possible Java
  17. calls
  18. --->
  19. <cffunction name="_init" hint="Constructor" access="public" returntype="JavaProxy" output="false">
  20. <cfargument name="class" hint="the java.lang.Class object this represents" type="any" required="Yes">
  21. <cfscript>
  22. var classLoader = createObject("java", "java.lang.ClassLoader").getSystemClassLoader();
  23. var objectClass = classLoader.loadClass("java.lang.Object");
  24. _setArray(createObject("java", "java.lang.reflect.Array"));
  25. _setClassMethod(objectClass.getMethod("getClass", JavaCast("null", 0)));
  26. _setObjectClass(objectClass);
  27. _setClass(arguments.class);
  28. _setModifier(createObject("java", "java.lang.reflect.Modifier"));
  29. _setStaticFields();
  30. _initMethodCollection();
  31. return this;
  32. </cfscript>
  33. </cffunction>
  34. <cffunction name="init" hint="create an instance of this object" access="public" returntype="any" output="false">
  35. <cfscript>
  36. var constructor = 0;
  37. var instance = 0;
  38. //make sure we only ever have one instance
  39. if(_hasClassInstance())
  40. {
  41. return _getClassInstance();
  42. }
  43. constructor = _resolveMethodByParams("Constructor", _getClass().getConstructors(), arguments);
  44. instance = constructor.newInstance(_buildArgumentArray(arguments));
  45. _setClassInstance(instance);
  46. return _getClassInstance();
  47. </cfscript>
  48. </cffunction>
  49. <cffunction name="onMissingMethod" access="public" returntype="any" output="false" hint="wires the coldfusion invocation to the Java Object">
  50. <cfargument name="missingMethodName" type="string" required="true" hint="" />
  51. <cfargument name="missingMethodArguments" type="struct" required="true" hint=""/>
  52. <cfscript>
  53. var method = _findMethod(arguments.missingMethodName, arguments.missingMethodArguments);
  54. if(_getModifier().isStatic(method.getModifiers()))
  55. {
  56. return method.invoke(JavaCast("null", 0), _buildArgumentArray(arguments.missingMethodArguments));
  57. }
  58. else
  59. {
  60. if(NOT _hasClassInstance())
  61. {
  62. //run the default constructor, just like in normal CF, if there is no instance
  63. init();
  64. }
  65. return method.invoke(_getClassInstance(), _buildArgumentArray(arguments.missingMethodArguments));
  66. }
  67. </cfscript>
  68. </cffunction>
  69. <!------------------------------------------- PUBLIC ------------------------------------------->
  70. <!------------------------------------------- PACKAGE ------------------------------------------->
  71. <!------------------------------------------- PRIVATE ------------------------------------------->
  72. <cffunction name="_setStaticFields" hint="loops around all the fields and sets the static one to this scope" access="private" returntype="void" output="false">
  73. <cfscript>
  74. var fields = _getClass().getFields();
  75. var counter = 1;
  76. var len = ArrayLen(fields);
  77. var field = 0;
  78. for(; counter <= len; counter++)
  79. {
  80. field = fields[counter];
  81. if(_getModifier().isStatic(field.getModifiers()))
  82. {
  83. this[field.getName()] = field.get(JavaCast("null", 0));
  84. }
  85. }
  86. </cfscript>
  87. </cffunction>
  88. <cffunction name="_buildArgumentArray" hint="builds an argument array out of the arguments" access="private" returntype="array" output="false">
  89. <cfargument name="arguments" hint="the arguments passed through" type="struct" required="Yes">
  90. <cfscript>
  91. var len = StructCount(arguments);
  92. var objArray = _getArray().newInstance(_getObjectClass(), len);
  93. var counter = 1;
  94. var obj = 0;
  95. for(; counter <= len; counter++)
  96. {
  97. obj = arguments[counter];
  98. _getArray().set(objArray, counter - 1, obj);
  99. }
  100. return objArray;
  101. </cfscript>
  102. </cffunction>
  103. <cffunction name="_findMethod" hint="finds the method that closest matches the signature" access="public" returntype="any" output="false">
  104. <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">
  105. <cfargument name="methodArgs" hint="the arguments to look for" type="struct" required="Yes">
  106. <cfscript>
  107. var decision = 0;
  108. if(StructKeyExists(_getMethodCollection(), arguments.methodName))
  109. {
  110. decision = StructFind(_getMethodCollection(), arguments.methodName);
  111. //if there is only one option, try it, it's only going to throw a runtime exception if it doesn't work.
  112. if(ArrayLen(decision) == 1)
  113. {
  114. return decision[1];
  115. }
  116. else
  117. {
  118. return _resolveMethodByParams(arguments.methodName, decision, arguments.methodArgs);
  119. }
  120. }
  121. throw("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#");
  122. </cfscript>
  123. </cffunction>
  124. <cffunction name="_resolveMethodByParams" hint="resolves the method to use by the parameters provided" access="private" returntype="any" output="false">
  125. <cfargument name="methodName" hint="the name of the method" type="string" required="Yes">
  126. <cfargument name="decision" hint="the array of methods to decide from" type="array" required="Yes">
  127. <cfargument name="methodArgs" hint="the arguments to look for" type="struct" required="Yes">
  128. <cfscript>
  129. var decisionLen = ArrayLen(arguments.decision);
  130. var method = 0;
  131. var counter = 1;
  132. var argLen = ArrayLen(arguments.methodArgs);
  133. var parameters = 0;
  134. var paramLen = 0;
  135. var pCounter = 0;
  136. var param = 0;
  137. var class = 0;
  138. var found = true;
  139. for(; counter <= decisionLen; counter++)
  140. {
  141. method = arguments.decision[counter];
  142. parameters = method.getParameterTypes();
  143. paramLen = ArrayLen(parameters);
  144. found = true;
  145. if(argLen eq paramLen)
  146. {
  147. for(pCounter = 1; pCounter <= paramLen AND found; pCounter++)
  148. {
  149. param = parameters[pCounter];
  150. class = _getClassMethod().invoke(arguments.methodArgs[pCounter], JavaCast("null", 0));
  151. if(param.isAssignableFrom(class))
  152. {
  153. found = true;
  154. }
  155. else if(param.isPrimitive()) //if it's a primitive, it can be mapped to object primtive classes
  156. {
  157. if(param.getName() eq "boolean" AND class.getName() eq "java.lang.Boolean")
  158. {
  159. found = true;
  160. }
  161. else if(param.getName() eq "int" AND class.getName() eq "java.lang.Integer")
  162. {
  163. found = true;
  164. }
  165. else if(param.getName() eq "long" AND class.getName() eq "java.lang.Long")
  166. {
  167. found = true;
  168. }
  169. else if(param.getName() eq "float" AND class.getName() eq "java.lang.Float")
  170. {
  171. found = true;
  172. }
  173. else if(param.getName() eq "double" AND class.getName() eq "java.lang.Double")
  174. {
  175. found = true;
  176. }
  177. else if(param.getName() eq "char" AND class.getName() eq "java.lang.Character")
  178. {
  179. found = true;
  180. }
  181. else if(param.getName() eq "byte" AND class.getName() eq "java.lang.Byte")
  182. {
  183. found = true;
  184. }
  185. else if(param.getName() eq "short" AND class.getName() eq "java.lang.Short")
  186. {
  187. found = true;
  188. }
  189. else
  190. {
  191. found = false;
  192. }
  193. }
  194. else
  195. {
  196. found = false;
  197. }
  198. }
  199. if(found)
  200. {
  201. return method;
  202. }
  203. }
  204. }
  205. throw("JavaProxy.MethodNotFoundException", "Could not find the designated method", "Could not find the method '#arguments.methodName#' in the class #_getClass().getName()#");
  206. </cfscript>
  207. </cffunction>
  208. <cffunction name="_initMethodCollection" hint="creates a method collection of all the methods that are available on the class (this may be cached externally later)" access="private" returntype="void" output="false">
  209. <cfscript>
  210. var methods = _getClass().getMethods();
  211. var len = ArrayLen(methods);
  212. var counter = 1;
  213. var method = 0;
  214. _setMethodCollection(StructNew());
  215. for(; counter <= len; counter++)
  216. {
  217. method = methods[counter];
  218. if(NOT StructKeyExists(_getMethodCollection(), method.getName()))
  219. {
  220. StructInsert(_getMethodCollection(), method.getName(), ArrayNew(1));
  221. }
  222. ArrayAppend(StructFind(_getMethodCollection(), method.getName()), method);
  223. }
  224. </cfscript>
  225. </cffunction>
  226. <cffunction name="_getMethodCollection" access="private" returntype="struct" output="false">
  227. <cfreturn instance.MethodCollection />
  228. </cffunction>
  229. <cffunction name="_setMethodCollection" access="private" returntype="void" output="false">
  230. <cfargument name="MethodCollection" type="struct" required="true">
  231. <cfset instance.MethodCollection = arguments.MethodCollection />
  232. </cffunction>
  233. <cffunction name="_hasClassInstance" hint="if the proxy has an instance yet" access="private" returntype="boolean" output="false">
  234. <cfreturn StructKeyExists(instance, "ClassInstance") />
  235. </cffunction>
  236. <cffunction name="_getClassInstance" access="private" returntype="any" output="false">
  237. <cfreturn instance.ClassInstance />
  238. </cffunction>
  239. <cffunction name="_setClassInstance" access="private" returntype="void" output="false">
  240. <cfargument name="ClassInstance" type="any" required="true">
  241. <cfset instance.ClassInstance = arguments.ClassInstance />
  242. </cffunction>
  243. <cffunction name="_getObjectClass" access="private" returntype="any" output="false">
  244. <cfreturn instance.ObjectClass />
  245. </cffunction>
  246. <cffunction name="_setObjectClass" access="private" returntype="void" output="false">
  247. <cfargument name="ObjectClass" type="any" required="true">
  248. <cfset instance.ObjectClass = arguments.ObjectClass />
  249. </cffunction>
  250. <cffunction name="_getArray" access="private" returntype="any" output="false">
  251. <cfreturn instance.Array />
  252. </cffunction>
  253. <cffunction name="_setArray" access="private" returntype="void" output="false">
  254. <cfargument name="Array" type="any" required="true">
  255. <cfset instance.Array = arguments.Array />
  256. </cffunction>
  257. <cffunction name="_getClassMethod" access="private" returntype="any" output="false">
  258. <cfreturn instance.ClassMethod />
  259. </cffunction>
  260. <cffunction name="_setClassMethod" access="private" returntype="void" output="false">
  261. <cfargument name="ClassMethod" type="any" required="true">
  262. <cfset instance.ClassMethod = arguments.ClassMethod />
  263. </cffunction>
  264. <cffunction name="_getClass" access="private" returntype="any" output="false">
  265. <cfreturn instance.Class />
  266. </cffunction>
  267. <cffunction name="_setClass" access="private" returntype="void" output="false">
  268. <cfargument name="Class" type="any" required="true">
  269. <cfset instance.Class = arguments.Class />
  270. </cffunction>
  271. <cffunction name="_getModifier" access="private" returntype="any" output="false">
  272. <cfreturn instance.Modifier />
  273. </cffunction>
  274. <cffunction name="_setModifier" access="private" returntype="void" output="false">
  275. <cfargument name="Modifier" type="any" required="true">
  276. <cfset instance.Modifier = arguments.Modifier />
  277. </cffunction>
  278. <cffunction name="throw" access="private" hint="Throws an Exception" output="false">
  279. <cfargument name="type" hint="The type of exception" type="string" required="Yes">
  280. <cfargument name="message" hint="The message to accompany the exception" type="string" required="Yes">
  281. <cfargument name="detail" type="string" hint="The detail message for the exception" required="No" default="">
  282. <cfthrow type="#arguments.type#" message="#arguments.message#" detail="#arguments.detail#">
  283. </cffunction>
  284. </cfcomponent>