PageRenderTime 28ms CodeModel.GetById 20ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 1ms

/wheels/vendor/javaloader/JavaProxy.cfc

http://cfwheels.googlecode.com/
ColdFusion CFScript | 354 lines | 281 code | 70 blank | 3 comment | 33 complexity | a553c6a24d795d3d75daf2febd0b2dd4 MD5 | raw file
  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>