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